Skip to content

Commit a7fc90a

Browse files
committed
Options to include all classpath elements
1 parent 43e6192 commit a7fc90a

File tree

16 files changed

+289
-77
lines changed

16 files changed

+289
-77
lines changed

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeReflection.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -231,7 +231,7 @@ public static void registerAllFields(Class<?> declaringClass) {
231231
* @since 23.0
232232
*/
233233
public static void registerAllDeclaredFields(Class<?> declaringClass) {
234-
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredFieldsQuery(ConfigurationCondition.alwaysTrue(), declaringClass);
234+
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredFields(ConfigurationCondition.alwaysTrue(), declaringClass);
235235
}
236236

237237
/**

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -48,7 +48,7 @@ public interface RuntimeReflectionSupport extends ReflectionRegistry {
4848

4949
void registerAllFieldsQuery(ConfigurationCondition condition, Class<?> clazz);
5050

51-
void registerAllDeclaredFieldsQuery(ConfigurationCondition condition, Class<?> clazz);
51+
void registerAllDeclaredFields(ConfigurationCondition condition, Class<?> clazz);
5252

5353
void registerAllConstructorsQuery(ConfigurationCondition condition, boolean queriedOnly, Class<?> clazz);
5454

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This changelog summarizes major changes to GraalVM Native Image.
99
* (GR-59864) Added JVM version check to the Native Image agent. The agent will abort execution if the JVM major version does not match the version it was built with, and warn if the full JVM version is different.
1010
* (GR-59135) Verify if hosted options passed to `native-image` exist prior to starting the builder. Provide suggestions how to fix unknown options early on.
1111
* (GR-61492) The experimental JDWP option is now present in standard GraalVM builds.
12+
* (GR-54953) Add options `-H:+EnableDynamicAccess`, `-H:EnableDynamicAccessForModule=<module>`, `-H:EnableDynamicAccessForPackage=<package>`, `-H:EnableDynamicAccessForClassPathEntry=<classpath-entry>` for bulk inclusion of elements for dynamic access. Using `-H:+EnableDynamicAccess` should make most of time images run immediately without requiring reachability metadata. Exceptions are multi-interface proxy classes and foreign function calls done via Panama.
1213

1314
## GraalVM for JDK 24 (Internal Version 24.2.0)
1415
* (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.

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ClassInclusionPolicy.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,28 @@ public void setBigBang(BigBang bb) {
5656
this.bb = bb;
5757
}
5858

59+
public static boolean isClassIncludedBase(Class<?> cls) {
60+
if (Feature.class.isAssignableFrom(cls)) {
61+
return false;
62+
}
63+
64+
if (AnnotationAccess.isAnnotationPresent(cls, TargetClass.class)) {
65+
return false;
66+
}
67+
try {
68+
Class<?> enclosingClass = cls.getEnclosingClass();
69+
return enclosingClass == null || isClassIncludedBase(enclosingClass);
70+
} catch (LinkageError e) {
71+
return true;
72+
}
73+
}
74+
5975
/**
6076
* Determine if the given class needs to be included in the image according to the policy.
6177
*/
6278
public boolean isClassIncluded(Class<?> cls) {
6379
Class<?> enclosingClass = cls.getEnclosingClass();
64-
return !Feature.class.isAssignableFrom(cls) && !AnnotationAccess.isAnnotationPresent(cls, TargetClass.class) && (enclosingClass == null || isClassIncluded(enclosingClass));
80+
return isClassIncludedBase(cls) && (enclosingClass == null || isClassIncluded(enclosingClass));
6581
}
6682

6783
/**

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ public void onTypeInstantiated(AnalysisType type) {
666666
/* Register the type as instantiated with all its super types. */
667667

668668
assert type.isInstantiated() : type;
669-
AnalysisError.guarantee(type.isArray() || (type.isInstanceClass() && !type.isAbstract()));
669+
AnalysisError.guarantee(type.isArray() || (type.isInstanceClass() && !type.isAbstract()), "Type %s must be either an array, or a non abstract instance class", type.getName());
670670

671671
TypeState typeState = TypeState.forExactType(this, type, true);
672672
TypeState typeStateNonNull = TypeState.forExactType(this, type, false);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,16 +1316,30 @@ public enum ReportingMode {
13161316
@Option(help = "Include all classes, methods, and fields from given modules", type = OptionType.Debug) //
13171317
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> IncludeAllFromModule = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());
13181318

1319+
@Option(help = "Include all classes, methods, fields, and resources from given modules for dynamic access", type = OptionType.Debug) //
1320+
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> EnableDynamicAccessForModule = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());
1321+
13191322
@Option(help = "Include all classes, methods, fields, and resources from given paths", type = OptionType.Debug) //
13201323
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> IncludeAllFromPath = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());
13211324

13221325
@Option(help = "Include all classes, methods and fields from the given packages", type = OptionType.Debug) //
13231326
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> IncludeAllFromPackage = new HostedOptionKey<>(
13241327
AccumulatingLocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
13251328

1329+
@Option(help = "Include all classes, methods and fields from the given packages for dynamic access", type = OptionType.Debug) //
1330+
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> EnableDynamicAccessForPackage = new HostedOptionKey<>(
1331+
AccumulatingLocatableMultiOptionValue.Strings.buildWithCommaDelimiter());
1332+
1333+
@Option(help = "Include all classes, methods, fields, and resources from given paths for dynamic access", type = OptionType.Debug) //
1334+
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> EnableDynamicAccessForClassPathEntry = new HostedOptionKey<>(
1335+
AccumulatingLocatableMultiOptionValue.Strings.build());
1336+
13261337
@Option(help = "Include all classes, methods, fields, and resources from the class path", type = OptionType.Debug) //
13271338
public static final HostedOptionKey<Boolean> IncludeAllFromClassPath = new HostedOptionKey<>(false);
13281339

1340+
@Option(help = "Include all classes, methods, fields, and resources for dynamic access for the whole classpath", type = OptionType.Debug) //
1341+
public static final HostedOptionKey<Boolean> EnableDynamicAccess = new HostedOptionKey<>(false);
1342+
13291343
public static boolean includeAll() {
13301344
return IncludeAllFromModule.hasBeenSet() || IncludeAllFromPath.hasBeenSet() || IncludeAllFromPackage.hasBeenSet() || IncludeAllFromClassPath.hasBeenSet();
13311345
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import static com.oracle.svm.core.MissingRegistrationUtils.throwMissingRegistrationErrors;
2828

29+
import java.lang.reflect.Modifier;
2930
import java.util.EnumSet;
3031
import java.util.Objects;
3132

@@ -159,7 +160,7 @@ public void registerNegativeQuery(ConfigurationCondition condition, String class
159160

160161
@Platforms(Platform.HOSTED_ONLY.class)
161162
public void registerUnsafeAllocated(ConfigurationCondition condition, Class<?> clazz) {
162-
if (!clazz.isArray()) {
163+
if (!clazz.isArray() && !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) {
163164
var conditionSet = unsafeInstantiatedClasses.putIfAbsent(clazz, RuntimeConditionSet.createHosted(condition));
164165
if (conditionSet != null) {
165166
conditionSet.addCondition(condition);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderSupportImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ public void collectResources(ResourceCollector resourceCollector) {
116116

117117
/* Collect remaining resources from classpath */
118118
classLoaderSupport.classpath().stream().parallel().forEach(classpathFile -> {
119-
boolean includeCurrent = classLoaderSupport.getJavaPathsToInclude().contains(classpathFile) || classLoaderSupport.includeAllFromClassPath();
119+
boolean includeCurrent = classLoaderSupport.getPathsToInclude().contains(classpathFile) || classLoaderSupport.includeAllFromClassPath() ||
120+
classLoaderSupport.getClassPathEntriesToEnableDynamicAccess().contains(classpathFile) || classLoaderSupport.isEnabledDynamicAccess();
120121
try {
121122
if (Files.isDirectory(classpathFile)) {
122123
scanDirectory(classpathFile, resourceCollector, includeCurrent);
@@ -132,7 +133,8 @@ public void collectResources(ResourceCollector resourceCollector) {
132133
private void collectResourceFromModule(ResourceCollector resourceCollector, ResourceLookupInfo info) {
133134
ModuleReference moduleReference = info.resolvedModule.reference();
134135
try (ModuleReader moduleReader = moduleReference.open()) {
135-
boolean includeCurrent = classLoaderSupport.getJavaModuleNamesToInclude().contains(info.resolvedModule().name());
136+
boolean includeCurrent = classLoaderSupport.getModuleNamesToInclude().contains(info.resolvedModule().name()) ||
137+
classLoaderSupport.getModuleNamesToEnableDynamicAccess().contains(info.resolvedModule().name());
136138
List<ConditionalResource> resourcesFound = new ArrayList<>();
137139
moduleReader.list().forEach(resourceName -> {
138140
var conditionsWithOrigins = shouldIncludeEntry(info.module, resourceCollector, resourceName, moduleReference.location().orElse(null), includeCurrent);

0 commit comments

Comments
 (0)