Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions sdk/src/org.graalvm.nativeimage/snapshot.sigtest
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ cons public init(java.lang.Throwable)
supr java.lang.Throwable
hfds serialVersionUID

CLSS public java.lang.LinkageError
cons public init()
cons public init(java.lang.String)
cons public init(java.lang.String,java.lang.Throwable)
supr java.lang.Error
hfds serialVersionUID

CLSS public java.lang.Exception
cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean)
cons public init()
Expand Down Expand Up @@ -230,7 +237,7 @@ meth public java.lang.Class<?> getDeclaringClass()
meth public java.lang.Class<?> getElementType()
meth public java.lang.String getElementName()
meth public java.lang.String getSignature()
supr java.lang.Error
supr java.lang.LinkageError
hfds declaringClass,elementName,elementType,serialVersionUID,signature

CLSS public final org.graalvm.nativeimage.MissingReflectionRegistrationError
Expand All @@ -239,7 +246,7 @@ meth public java.lang.Class<?> getDeclaringClass()
meth public java.lang.Class<?> getElementType()
meth public java.lang.Class<?>[] getParameterTypes()
meth public java.lang.String getElementName()
supr java.lang.Error
supr java.lang.LinkageError
hfds declaringClass,elementName,elementType,parameterTypes,serialVersionUID

CLSS public abstract interface org.graalvm.nativeimage.ObjectHandle
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -74,7 +74,7 @@
*
* @since 24.1
*/
public final class MissingJNIRegistrationError extends Error {
public final class MissingJNIRegistrationError extends LinkageError {
@Serial private static final long serialVersionUID = -8940056537864516986L;

private final Class<?> elementType;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -91,7 +91,7 @@
*
* @since 23.0
*/
public final class MissingReflectionRegistrationError extends Error {
public final class MissingReflectionRegistrationError extends LinkageError {
@Serial private static final long serialVersionUID = 2764341882856270640L;

private final Class<?> elementType;
Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-59869) Implemented initial optimization of Java Vector API (JEP 338) operations in native images. See the compiler changelog for more details.
* (GR-63268) Reflection and JNI queries do not require metadata entries to throw the expected JDK exception when querying a class that doesn't exist under `--exact-reachability-metadata` if the query cannot possibly be a valid class name
* (GR-47881) Remove the total number of loaded types, fields, and methods from the build output, deprecated these metrics in the build output schema, and removed already deprecated build output metrics.
* (GR-64619) Missing registration errors are now subclasses of `LinkageError`

## GraalVM for JDK 24 (Internal Version 24.2.0)
* (GR-59717) Added `DuringSetupAccess.registerObjectReachabilityHandler` to allow registering a callback that is executed when an object of a specified type is marked as reachable during heap scanning.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;

import com.oracle.svm.core.util.ExitStatus;
import com.oracle.svm.core.util.VMError;

public final class MissingRegistrationUtils {

Expand All @@ -46,7 +48,7 @@ public static SubstrateOptions.ReportingMode missingRegistrationReportingMode()
private static final AtomicReference<Set<String>> seenOutputs = new AtomicReference<>(null);

public static void report(Error exception, StackTraceElement responsibleClass) {
if (responsibleClass != null && !MissingRegistrationSupport.singleton().reportMissingRegistrationErrors(responsibleClass)) {
if (missingRegistrationErrorsSuspended.get() || (responsibleClass != null && !MissingRegistrationSupport.singleton().reportMissingRegistrationErrors(responsibleClass))) {
return;
}
switch (missingRegistrationReportingMode()) {
Expand Down Expand Up @@ -104,6 +106,25 @@ public static void report(Error exception, StackTraceElement responsibleClass) {
}
}

private static final ThreadLocal<Boolean> missingRegistrationErrorsSuspended = ThreadLocal.withInitial(() -> false);

/**
* Code executing inside this function will temporarily revert to throwing JDK exceptions like
* ({@code ClassNotFoundException} when encountering a situation that would normally cause a
* missing registration error. This is currently required during resource bundle lookups, where
* encountering an unregistered class can mean that the corresponding locale isn't included in
* the image, and is not a reason to abort the lookup completely.
*/
public static <T> T runIgnoringMissingRegistrations(Supplier<T> callback) {
VMError.guarantee(!missingRegistrationErrorsSuspended.get());
try {
missingRegistrationErrorsSuspended.set(true);
return callback.get();
} finally {
missingRegistrationErrorsSuspended.set(false);
}
}

private static void printLine(StringBuilder sb, Object object) {
sb.append(" ").append(object).append(System.lineSeparator());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@
import java.lang.invoke.MethodType;
import java.lang.reflect.Member;

import org.graalvm.nativeimage.MissingReflectionRegistrationError;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Inject;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.methodhandles.Target_java_lang_invoke_MethodHandleNatives;
import com.oracle.svm.core.util.BasedOnJDKFile;
import com.oracle.svm.core.util.VMError;

@TargetClass(className = "java.lang.invoke.MemberName")
public final class Target_java_lang_invoke_MemberName {
Expand Down Expand Up @@ -81,7 +86,57 @@ public final class Target_java_lang_invoke_MemberName {

@SuppressWarnings("static-method")
@Substitute
private boolean vminfoIsConsistent() {
boolean vminfoIsConsistent() {
return true; /* The substitution class doesn't use the same internals as the JDK */
}

@Alias
@Override
protected native Target_java_lang_invoke_MemberName clone();

@Alias
native void ensureTypeVisible(Class<?> refc);

@Alias
public native boolean isResolved();

@Alias
native boolean referenceKindIsConsistent();

@Alias
native void initResolved(boolean isResolved);
}

@TargetClass(className = "java.lang.invoke.MemberName", innerClass = "Factory")
final class Target_java_lang_invoke_MemberName_Factory {
@Substitute
@SuppressWarnings("static-method")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/b685ea54081fcf54a6567dddb49b63435a6e1ea4/src/java.base/share/classes/java/lang/invoke/MemberName.java#L937-L973")
private Target_java_lang_invoke_MemberName resolve(byte refKind, Target_java_lang_invoke_MemberName ref, Class<?> lookupClass, int allowedModes,
boolean speculativeResolve) {
Target_java_lang_invoke_MemberName m = ref.clone();
assert (refKind == m.getReferenceKind());
try {
m = Target_java_lang_invoke_MethodHandleNatives.resolve(m, lookupClass, allowedModes, speculativeResolve);
if (m == null) {
VMError.guarantee(speculativeResolve, "non-speculative resolution should return member name or throw");
return null;
}
m.ensureTypeVisible(m.getDeclaringClass());
m.resolution = null;
} catch (ClassNotFoundException | LinkageError ex) {
if (ex instanceof MissingReflectionRegistrationError e) {
/* Bypass the LinkageError catch below */
throw e;
}
VMError.guarantee(m != null, "speculative resolution should not throw");
assert (!m.isResolved());
m.resolution = ex;
return m;
}
assert (m.referenceKindIsConsistent());
m.initResolved(true);
assert (m.vminfoIsConsistent());
return m;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;

import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.svm.core.MissingRegistrationUtils;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.RecomputeFieldValue;
import com.oracle.svm.core.annotate.Substitute;
Expand Down Expand Up @@ -115,7 +117,12 @@ private static ResourceBundle getBundleImpl(String baseName,
if (!ImageSingletons.lookup(LocalizationSupport.class).isRegisteredBundleLookup(baseName, locale, control)) {
MissingResourceRegistrationUtils.missingResourceBundle(baseName);
}
return getBundleImpl(callerModule, callerModule, baseName, locale, control);
return MissingRegistrationUtils.runIgnoringMissingRegistrations(new Supplier<ResourceBundle>() {
@Override
public ResourceBundle get() {
return getBundleImpl(callerModule, callerModule, baseName, locale, control);
}
});
}

// find resource bundles from unnamed module of given class loader
Expand All @@ -129,7 +136,12 @@ private static ResourceBundle getBundleImpl(String baseName,
if (!ImageSingletons.lookup(LocalizationSupport.class).isRegisteredBundleLookup(baseName, locale, control)) {
MissingResourceRegistrationUtils.missingResourceBundle(baseName);
}
return getBundleImpl(callerModule, unnamedModule, baseName, locale, control);
return MissingRegistrationUtils.runIgnoringMissingRegistrations(new Supplier<ResourceBundle>() {
@Override
public ResourceBundle get() {
return getBundleImpl(callerModule, unnamedModule, baseName, locale, control);
}
});
}

@Alias
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
*/
@SuppressWarnings("unused")
@TargetClass(className = "java.lang.invoke.MethodHandleNatives")
final class Target_java_lang_invoke_MethodHandleNatives {
public final class Target_java_lang_invoke_MethodHandleNatives {

/*
* MemberName native constructor. We need to resolve the actual type and flags of the member and
Expand Down Expand Up @@ -209,7 +209,7 @@ private static Object getMemberVMInfo(Target_java_lang_invoke_MemberName self) {
static native String refKindName(byte refKind);

@Substitute
static Target_java_lang_invoke_MemberName resolve(Target_java_lang_invoke_MemberName self, Class<?> caller, int lookupMode, boolean speculativeResolve)
public static Target_java_lang_invoke_MemberName resolve(Target_java_lang_invoke_MemberName self, Class<?> caller, int lookupMode, boolean speculativeResolve)
throws LinkageError, ClassNotFoundException {
Class<?> declaringClass = self.getDeclaringClass();
Target_java_lang_invoke_MemberName resolved = Util_java_lang_invoke_MethodHandleNatives.resolve(self, caller, speculativeResolve);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
* The purpose of this exception is to easily discover unregistered elements and to assure that all
* serialization or deserialization operations have expected behavior.
*/
public final class MissingSerializationRegistrationError extends Error {
public final class MissingSerializationRegistrationError extends LinkageError {
@Serial private static final long serialVersionUID = 2764341882856270641L;
private final Class<?> culprit;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ private void handleAliasClass(Class<?> annotatedClass, Class<?> originalClass, T
}

private void handleMethodInAliasClass(Executable annotatedMethod, Class<?> originalClass) {
if (skipExcludedPlatform(annotatedMethod)) {
if (skipExcludedPlatform(annotatedMethod) || annotatedMethod.isSynthetic()) {
return;
}

Expand Down Expand Up @@ -482,7 +482,7 @@ private boolean skipExcludedPlatform(AnnotatedElement annotatedMethod) {
}

private void handleFieldInAliasClass(Field annotatedField, Class<?> originalClass) {
if (skipExcludedPlatform(annotatedField)) {
if (skipExcludedPlatform(annotatedField) || annotatedField.isSynthetic()) {
return;
}

Expand Down