From 39e06057b0c35d87635dd88ce024045ea71ba2d8 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Mon, 13 Oct 2025 09:53:16 +0200 Subject: [PATCH 1/4] Improve Crema with `--exact-reachability-metadata` --- .../nativeimage/impl/ClassLoading.java | 39 +++++++++++++++++-- .../svm/core/hub/crema/CremaSupport.java | 8 ++-- .../metadata/CremaResolvedJavaFieldImpl.java | 8 +++- .../svm/interpreter/CremaRuntimeAccess.java | 10 +++-- .../RuntimeInterpreterConstantPool.java | 32 ++++++++++----- 5 files changed, 76 insertions(+), 21 deletions(-) diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java index 5088604a697f..21f62498b31e 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java @@ -69,13 +69,38 @@ public static ArbitraryClassLoadingScope allowArbitraryClassLoading() { if (!isSupported()) { throw new IllegalStateException("Runtime class loading is not supported. It must be enabled at build-time with -H:+RuntimeClassLoading."); } - return new ArbitraryClassLoadingScope(); + return new RealArbitraryClassLoadingScope(); } - public static final class ArbitraryClassLoadingScope implements AutoCloseable { + /** + * Conditionally opens a scope in which class loading is not constrained by the reflection + * configuration. If {@code allowArbitraryClassLoading} is true, behaves like + * {@link #allowArbitraryClassLoading()}. Otherwise, it has no effect. + * + * @throws IllegalStateException if class loading is not {@linkplain #isSupported() supported} + * and {@code allowArbitraryClassLoading} is true. + * + * @see #allowArbitraryClassLoading() + */ + public static ArbitraryClassLoadingScope allowArbitraryClassLoading(boolean allowArbitraryClassLoading) { + if (allowArbitraryClassLoading) { + return allowArbitraryClassLoading(); + } + return NoopScope.INSTANCE; + } + + public abstract static class ArbitraryClassLoadingScope implements AutoCloseable { + private ArbitraryClassLoadingScope() { + } + + @Override + public abstract void close(); + } + + public static final class RealArbitraryClassLoadingScope extends ArbitraryClassLoadingScope { private boolean closed; - ArbitraryClassLoadingScope() { + RealArbitraryClassLoadingScope() { if (!ImageInfo.inImageRuntimeCode()) { return; } @@ -94,4 +119,12 @@ public void close() { ClassLoadingSupport.singleton().endIgnoreReflectionConfigurationScope(); } } + + private static final class NoopScope extends ArbitraryClassLoadingScope { + private static final NoopScope INSTANCE = new NoopScope(); + + @Override + public void close() { + } + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/CremaSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/CremaSupport.java index 2657b7956005..9d4cb0e43538 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/CremaSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/CremaSupport.java @@ -39,10 +39,10 @@ import com.oracle.svm.espresso.classfile.descriptors.Symbol; import com.oracle.svm.espresso.classfile.descriptors.Type; -import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.UnresolvedJavaType; public interface CremaSupport { @Platforms(Platform.HOSTED_ONLY.class) @@ -88,7 +88,7 @@ interface CremaDispatchTable { Class toClass(ResolvedJavaType resolvedJavaType); - default Class resolveOrThrow(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) { + default Class resolveOrThrow(UnresolvedJavaType unresolvedJavaType, ResolvedJavaType accessingClass) { ByteSequence type = ByteSequence.create(unresolvedJavaType.getName()); Symbol symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type); return resolveOrThrow(symbolicType, accessingClass); @@ -96,7 +96,7 @@ default Class resolveOrThrow(JavaType unresolvedJavaType, ResolvedJavaType ac Class resolveOrThrow(Symbol type, ResolvedJavaType accessingClass); - default Class resolveOrNull(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) { + default Class resolveOrNull(UnresolvedJavaType unresolvedJavaType, ResolvedJavaType accessingClass) { ByteSequence type = ByteSequence.create(unresolvedJavaType.getName()); Symbol symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type); return resolveOrNull(symbolicType, accessingClass); @@ -104,7 +104,7 @@ default Class resolveOrNull(JavaType unresolvedJavaType, ResolvedJavaType acc Class resolveOrNull(Symbol type, ResolvedJavaType accessingClass); - default Class findLoadedClass(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) { + default Class findLoadedClass(UnresolvedJavaType unresolvedJavaType, ResolvedJavaType accessingClass) { ByteSequence type = ByteSequence.create(unresolvedJavaType.getName()); Symbol symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type); return findLoadedClass(symbolicType, accessingClass); diff --git a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/CremaResolvedJavaFieldImpl.java b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/CremaResolvedJavaFieldImpl.java index 52e6f72a5515..92896f527e05 100644 --- a/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/CremaResolvedJavaFieldImpl.java +++ b/substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/CremaResolvedJavaFieldImpl.java @@ -24,6 +24,8 @@ */ package com.oracle.svm.interpreter.metadata; +import org.graalvm.nativeimage.impl.ClassLoading; + import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.crema.CremaResolvedJavaField; import com.oracle.svm.core.hub.crema.CremaSupport; @@ -78,8 +80,10 @@ public JavaType getType() { @Override public InterpreterResolvedJavaType getResolvedType() { if (resolvedType == null) { - Class cls = CremaSupport.singleton().resolveOrThrow(getSymbolicType(), getDeclaringClass()); - resolvedType = (InterpreterResolvedJavaType) DynamicHub.fromClass(cls).getInterpreterType(); + try (var _ = ClassLoading.allowArbitraryClassLoading()) { + Class cls = CremaSupport.singleton().resolveOrThrow(getSymbolicType(), getDeclaringClass()); + resolvedType = (InterpreterResolvedJavaType) DynamicHub.fromClass(cls).getInterpreterType(); + } } return resolvedType; } diff --git a/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/CremaRuntimeAccess.java b/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/CremaRuntimeAccess.java index 2797c66b50ff..2f4f5c7adc39 100644 --- a/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/CremaRuntimeAccess.java +++ b/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/CremaRuntimeAccess.java @@ -27,6 +27,8 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import org.graalvm.nativeimage.impl.ClassLoading; + import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.crema.CremaSupport; import com.oracle.svm.core.hub.registry.SymbolsSupport; @@ -94,9 +96,11 @@ public RuntimeException throwError(ErrorType errorType, String messageFormat, Ob @Override public InterpreterResolvedObjectType lookupOrLoadType(Symbol type, InterpreterResolvedJavaType accessingClass) { - Class result = CremaSupport.singleton().resolveOrThrow(type, accessingClass); - assert !result.isPrimitive(); - return (InterpreterResolvedObjectType) DynamicHub.fromClass(result).getInterpreterType(); + try (var _ = ClassLoading.allowArbitraryClassLoading()) { + Class result = CremaSupport.singleton().resolveOrThrow(type, accessingClass); + assert !result.isPrimitive(); + return (InterpreterResolvedObjectType) DynamicHub.fromClass(result).getInterpreterType(); + } } @Override diff --git a/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/RuntimeInterpreterConstantPool.java b/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/RuntimeInterpreterConstantPool.java index fa99e995319c..4ca7eb085f96 100644 --- a/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/RuntimeInterpreterConstantPool.java +++ b/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/RuntimeInterpreterConstantPool.java @@ -26,6 +26,9 @@ import java.lang.invoke.MethodType; +import org.graalvm.nativeimage.impl.ClassLoading; + +import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.crema.CremaSupport; import com.oracle.svm.core.hub.registry.SymbolsSupport; import com.oracle.svm.core.methodhandles.Target_java_lang_invoke_MethodHandleNatives; @@ -137,17 +140,25 @@ private String resolveStringConstant(int stringIndex, @SuppressWarnings("unused" return string; } - private InterpreterResolvedJavaType resolveClassConstant(int classIndex, InterpreterResolvedJavaType accessingKlass) { + private static InterpreterResolvedObjectType resolveObjectType(Symbol type, InterpreterResolvedObjectType accessingClass) { + DynamicHub hub = DynamicHub.fromClass(CremaSupport.singleton().resolveOrThrow(type, accessingClass)); + assert !hub.isPrimitive(); + return (InterpreterResolvedObjectType) hub.getInterpreterType(); + } + + private InterpreterResolvedJavaType resolveClassConstant(int classIndex, InterpreterResolvedObjectType accessingKlass) { assert accessingKlass != null; assert tagAt(classIndex) == Tag.CLASS; Object entry = this.cachedEntries[classIndex]; Symbol type = null; + boolean allowArbitraryClassLoading; if (entry == null) { // CP comes from dynamically loaded .class file. Symbol className = this.className(classIndex); type = SymbolsSupport.getTypes().fromClassNameEntry(className); + allowArbitraryClassLoading = true; } else if (entry instanceof UnresolvedJavaType unresolvedJavaType) { Throwable cause = unresolvedJavaType.getCause(); if (cause != null) { @@ -155,14 +166,15 @@ private InterpreterResolvedJavaType resolveClassConstant(int classIndex, Interpr } // CP comes from build-time JVMCI type, derive type from UnresolvedJavaType. type = SymbolsSupport.getTypes().getOrCreateValidType(unresolvedJavaType.getName()); + allowArbitraryClassLoading = false; } else { throw VMError.shouldNotReachHere("Invalid cached CP entry, expected unresolved type, but got " + entry); } assert type != null; - try { - InterpreterResolvedObjectType result = CremaRuntimeAccess.getInstance().lookupOrLoadType(type, accessingKlass); + try (var _ = ClassLoading.allowArbitraryClassLoading(allowArbitraryClassLoading)) { + InterpreterResolvedObjectType result = resolveObjectType(type, accessingKlass); return result; } catch (LinkageError e) { // Comment from Hotspot: @@ -201,7 +213,7 @@ private InterpreterResolvedJavaField resolveFieldRefConstant(int fieldIndex, Int Symbol holderType = SymbolsSupport.getTypes().getOrCreateValidType(unresolvedJavaField.getDeclaringClass().getName()); assert !TypeSymbols.isPrimitive(holderType) && !TypeSymbols.isArray(holderType); // Perf. note: The holder is re-resolved every-time (never cached). - holder = CremaRuntimeAccess.getInstance().lookupOrLoadType(holderType, accessingClass); + holder = resolveObjectType(holderType, accessingClass); } else { throw VMError.shouldNotReachHere("Invalid cached CP entry, expected unresolved field, but got " + entry); } @@ -237,7 +249,7 @@ private InterpreterResolvedJavaMethod resolveClassMethodRefConstant(int methodIn methodSignature = SymbolsSupport.getSignatures().getOrCreateValidSignature(unresolvedJavaMethod.getSignature().toMethodDescriptor()); Symbol holderType = SymbolsSupport.getTypes().getOrCreateValidType(unresolvedJavaMethod.getDeclaringClass().getName()); // Perf. note: The holder is re-resolved every-time (never cached). - holder = CremaRuntimeAccess.getInstance().lookupOrLoadType(holderType, accessingClass); + holder = resolveObjectType(holderType, accessingClass); } else { throw VMError.shouldNotReachHere("Invalid cached CP entry, expected unresolved method, but got " + entry); } @@ -275,7 +287,7 @@ private InterpreterResolvedJavaMethod resolveInterfaceMethodRefConstant(int inte methodSignature = SymbolsSupport.getSignatures().getOrCreateValidSignature(unresolvedJavaMethod.getSignature().toMethodDescriptor()); Symbol holderType = SymbolsSupport.getTypes().getOrCreateValidType(unresolvedJavaMethod.getDeclaringClass().getName()); // Perf. note: The holder is re-resolved every-time (never cached). - holder = CremaRuntimeAccess.getInstance().lookupOrLoadType(holderType, accessingClass); + holder = resolveObjectType(holderType, accessingClass); } else { throw VMError.shouldNotReachHere("Invalid cached CP entry, expected unresolved method, but got " + entry); } @@ -322,8 +334,10 @@ public static MethodType signatureToMethodType(Symbol[] signature, Interpr } private static Class resolveSymbolAndAccessCheck(InterpreterResolvedObjectType accessingClass, Symbol type) { - Class clazz = CremaSupport.singleton().resolveOrThrow(type, accessingClass); - // GR-62339 check access - return clazz; + try (var _ = ClassLoading.allowArbitraryClassLoading()) { + Class clazz = CremaSupport.singleton().resolveOrThrow(type, accessingClass); + // GR-62339 check access + return clazz; + } } } From a0c19d4a0692ac2cd6f1b2386fee5f5f884004f7 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Mon, 3 Nov 2025 11:40:07 +0100 Subject: [PATCH 2/4] Interpreter: fix exceptions thrown during class resolution --- .../oracle/svm/interpreter/Interpreter.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/Interpreter.java b/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/Interpreter.java index aa4b602cf66e..deb8f2a8eeea 100644 --- a/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/Interpreter.java +++ b/substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/Interpreter.java @@ -1497,9 +1497,8 @@ private static InterpreterResolvedJavaType resolveType(InterpreterResolvedJavaMe missingType = unresolvedJavaType; } throw noClassDefFoundError(opcode, missingType); - } catch (ClassFormatError e) { - // Out-of-bounds CPI or mis-matching tag. - throw SemanticJavaException.raise(e); + } catch (Throwable t) { + throw SemanticJavaException.raise(t); } } @@ -1512,10 +1511,8 @@ private static InterpreterResolvedJavaType resolveTypeOrNullIfUnresolvable(Inter return getConstantPool(method).resolvedTypeAt(method.getDeclaringClass(), cpi); } catch (UnsupportedResolutionException e) { return null; - } catch (ClassFormatError e) { - // Out-of-bounds CPI or mis-matching tag. - // Unrelated to resolution, just propagate the error. - throw SemanticJavaException.raise(e); + } catch (Throwable t) { + throw SemanticJavaException.raise(t); } } @@ -1533,9 +1530,8 @@ private static InterpreterResolvedJavaMethod resolveMethod(InterpreterResolvedJa missingMethod = unresolvedJavaMethod; } throw noSuchMethodError(opcode, missingMethod); - } catch (ClassFormatError e) { - // Out-of-bounds CPI or mis-matching tag. - throw SemanticJavaException.raise(e); + } catch (Throwable t) { + throw SemanticJavaException.raise(t); } } @@ -1553,9 +1549,8 @@ private static InterpreterResolvedJavaField resolveField(InterpreterResolvedJava missingField = unresolvedJavaField; } throw noSuchFieldError(opcode, missingField); - } catch (ClassFormatError e) { - // Out of bounds CPI or mis-matching tag. - throw SemanticJavaException.raise(e); + } catch (Throwable t) { + throw SemanticJavaException.raise(t); } } From 861559d54ac6382f9a567c3884678ea5d537e9ca Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Mon, 6 Oct 2025 09:53:24 +0200 Subject: [PATCH 3/4] Update owners files around crema --- .../src/com/oracle/svm/core/hub/OWNERS.toml | 5 +++++ .../src/com/oracle/svm/core/hub/crema/OWNERS.toml | 5 +++++ .../src/com/oracle/svm/core/hub/registry/OWNERS.toml | 5 +++++ .../src/com.oracle.svm.interpreter.metadata/OWNERS.toml | 8 +------- substratevm/src/com.oracle.svm.interpreter/OWNERS.toml | 8 +------- substratevm/src/com.oracle.svm.jdwp.bridge/OWNERS.toml | 7 ------- substratevm/src/com.oracle.svm.jdwp.resident/OWNERS.toml | 7 ------- substratevm/src/com.oracle.svm.jdwp.server/OWNERS.toml | 7 ------- 8 files changed, 17 insertions(+), 35 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/OWNERS.toml create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/OWNERS.toml diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml index b8a198d08ff3..43e8efa30e47 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/OWNERS.toml @@ -6,3 +6,8 @@ all = [ ] any = [ ] +[[rule]] +files = "RuntimeClassLoading.java RuntimeDynamicHubMetadata.java RuntimeReflectionMetadata.java" +all = [ + "gilles.m.duboscq@oracle.com", +] diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/OWNERS.toml b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/OWNERS.toml new file mode 100644 index 000000000000..0e990dadb48f --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/OWNERS.toml @@ -0,0 +1,5 @@ +[[rule]] +files = "*" +all = [ + "gilles.m.duboscq@oracle.com", +] diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/OWNERS.toml b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/OWNERS.toml new file mode 100644 index 000000000000..0e990dadb48f --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/OWNERS.toml @@ -0,0 +1,5 @@ +[[rule]] +files = "*" +all = [ + "gilles.m.duboscq@oracle.com", +] diff --git a/substratevm/src/com.oracle.svm.interpreter.metadata/OWNERS.toml b/substratevm/src/com.oracle.svm.interpreter.metadata/OWNERS.toml index ae3421269b88..67c7e4be1111 100644 --- a/substratevm/src/com.oracle.svm.interpreter.metadata/OWNERS.toml +++ b/substratevm/src/com.oracle.svm.interpreter.metadata/OWNERS.toml @@ -1,12 +1,6 @@ [[rule]] files = "*" all = [ - "alfonso.peterssen@oracle.com", "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", -] -any = [ - "alfonso.peterssen@oracle.com", - "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", + "gilles.m.duboscq@oracle.com", ] diff --git a/substratevm/src/com.oracle.svm.interpreter/OWNERS.toml b/substratevm/src/com.oracle.svm.interpreter/OWNERS.toml index ae3421269b88..67c7e4be1111 100644 --- a/substratevm/src/com.oracle.svm.interpreter/OWNERS.toml +++ b/substratevm/src/com.oracle.svm.interpreter/OWNERS.toml @@ -1,12 +1,6 @@ [[rule]] files = "*" all = [ - "alfonso.peterssen@oracle.com", "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", -] -any = [ - "alfonso.peterssen@oracle.com", - "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", + "gilles.m.duboscq@oracle.com", ] diff --git a/substratevm/src/com.oracle.svm.jdwp.bridge/OWNERS.toml b/substratevm/src/com.oracle.svm.jdwp.bridge/OWNERS.toml index ae3421269b88..f743f4c4a24b 100644 --- a/substratevm/src/com.oracle.svm.jdwp.bridge/OWNERS.toml +++ b/substratevm/src/com.oracle.svm.jdwp.bridge/OWNERS.toml @@ -1,12 +1,5 @@ [[rule]] files = "*" all = [ - "alfonso.peterssen@oracle.com", "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", -] -any = [ - "alfonso.peterssen@oracle.com", - "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", ] diff --git a/substratevm/src/com.oracle.svm.jdwp.resident/OWNERS.toml b/substratevm/src/com.oracle.svm.jdwp.resident/OWNERS.toml index ae3421269b88..f743f4c4a24b 100644 --- a/substratevm/src/com.oracle.svm.jdwp.resident/OWNERS.toml +++ b/substratevm/src/com.oracle.svm.jdwp.resident/OWNERS.toml @@ -1,12 +1,5 @@ [[rule]] files = "*" all = [ - "alfonso.peterssen@oracle.com", "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", -] -any = [ - "alfonso.peterssen@oracle.com", - "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", ] diff --git a/substratevm/src/com.oracle.svm.jdwp.server/OWNERS.toml b/substratevm/src/com.oracle.svm.jdwp.server/OWNERS.toml index ae3421269b88..f743f4c4a24b 100644 --- a/substratevm/src/com.oracle.svm.jdwp.server/OWNERS.toml +++ b/substratevm/src/com.oracle.svm.jdwp.server/OWNERS.toml @@ -1,12 +1,5 @@ [[rule]] files = "*" all = [ - "alfonso.peterssen@oracle.com", "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", -] -any = [ - "alfonso.peterssen@oracle.com", - "bernhard.urban-forster@oracle.com", - "martin.entlicher@oracle.com", ] From 762d33c3bc9c3831798b87d69fd2cb50a83855f6 Mon Sep 17 00:00:00 2001 From: Gilles Duboscq Date: Mon, 3 Nov 2025 17:52:31 +0100 Subject: [PATCH 4/4] Improve javadoc for org.graalvm.nativeimage.impl.ClassLoading(Support) --- .../graalvm/nativeimage/impl/ClassLoading.java | 9 +++++---- .../nativeimage/impl/ClassLoadingSupport.java | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java index 21f62498b31e..7f7bac164f04 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java @@ -60,8 +60,9 @@ public static boolean isSupported() { } /** - * Opens a scope in which class loading is not constrained by the reflection configuration. Once - * the returned {@link AutoCloseable} is closed, the previous state is restored. + * Opens a scope in which class loading is not constrained by the reflection configuration for + * the current thread. Once the returned {@link AutoCloseable} is closed, the previous state is + * restored. * * @throws IllegalStateException if class loading is not {@linkplain #isSupported() supported}. */ @@ -74,8 +75,8 @@ public static ArbitraryClassLoadingScope allowArbitraryClassLoading() { /** * Conditionally opens a scope in which class loading is not constrained by the reflection - * configuration. If {@code allowArbitraryClassLoading} is true, behaves like - * {@link #allowArbitraryClassLoading()}. Otherwise, it has no effect. + * configuration for the current thread. If {@code allowArbitraryClassLoading} is true, behaves + * like {@link #allowArbitraryClassLoading()}. Otherwise, it has no effect. * * @throws IllegalStateException if class loading is not {@linkplain #isSupported() supported} * and {@code allowArbitraryClassLoading} is true. diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoadingSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoadingSupport.java index 5c4b10bd30aa..afcb11973622 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoadingSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoadingSupport.java @@ -47,11 +47,28 @@ static ClassLoadingSupport singleton() { return ImageSingletons.lookup(ClassLoadingSupport.class); } + /** + * Returns whether runtime class loading is supported. + */ boolean isSupported(); + /** + * Returns false iff the current thread is in a + * {@linkplain #startIgnoreReflectionConfigurationScope() scope} where reflection configuration + * is ignored. + */ boolean followReflectionConfiguration(); + /** + * Starts a scope in which the reflection configuration is ignored for runtime class loading. + *

+ * That scope can be closed by calling {@link #endIgnoreReflectionConfigurationScope()}. + */ void startIgnoreReflectionConfigurationScope(); + /** + * Ends a scope started by {@link #startIgnoreReflectionConfigurationScope()} for the current + * thread. + */ void endIgnoreReflectionConfigurationScope(); }