Skip to content

Commit 31132c5

Browse files
committed
[GR-48338] Add options to include all classes from the class path
PullRequest: graal/16006
2 parents 5fc14c4 + ccd5aa3 commit 31132c5

File tree

6 files changed

+42
-16
lines changed

6 files changed

+42
-16
lines changed

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
package com.oracle.graal.pointsto;
2626

2727
import java.io.PrintWriter;
28+
import java.lang.reflect.Constructor;
29+
import java.lang.reflect.Field;
30+
import java.lang.reflect.Method;
2831
import java.util.Arrays;
2932
import java.util.Collections;
3033
import java.util.List;
@@ -350,17 +353,25 @@ public final boolean executorIsStarted() {
350353

351354
@Override
352355
public void registerTypeForBaseImage(Class<?> cls) {
353-
if (classInclusionPolicy.isClassIncluded(cls)) {
356+
if (getOrDefault(cls, classInclusionPolicy::isClassIncluded, false)) {
354357
classInclusionPolicy.includeClass(cls);
355-
Stream.concat(Arrays.stream(cls.getDeclaredConstructors()), Arrays.stream(cls.getDeclaredMethods()))
358+
Stream.concat(Arrays.stream(getOrDefault(cls, Class::getDeclaredConstructors, new Constructor<?>[0])), Arrays.stream(getOrDefault(cls, Class::getDeclaredMethods, new Method[0])))
356359
.filter(classInclusionPolicy::isMethodIncluded)
357360
.forEach(classInclusionPolicy::includeMethod);
358-
Arrays.stream(cls.getDeclaredFields())
361+
Arrays.stream(getOrDefault(cls, Class::getDeclaredFields, new Field[0]))
359362
.filter(classInclusionPolicy::isFieldIncluded)
360363
.forEach(classInclusionPolicy::includeField);
361364
}
362365
}
363366

367+
public static <T, U> U getOrDefault(T cls, Function<T, U> getMembers, U backup) {
368+
try {
369+
return getMembers.apply(cls);
370+
} catch (NoClassDefFoundError | IncompatibleClassChangeError e) {
371+
return backup;
372+
}
373+
}
374+
364375
/**
365376
* Provide a non-null position. Some flows like newInstance and invoke require a non-null
366377
* position, for others is just better. The constructed position is best-effort, i.e., it

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
import java.lang.reflect.Modifier;
3131

3232
import org.graalvm.nativeimage.AnnotationAccess;
33+
import org.graalvm.nativeimage.hosted.Feature;
3334

3435
import com.oracle.graal.pointsto.meta.AnalysisMethod;
36+
import com.oracle.svm.core.annotate.TargetClass;
3537

3638
import jdk.graal.compiler.api.replacements.Fold;
3739

@@ -55,7 +57,10 @@ public void setBigBang(BigBang bb) {
5557
/**
5658
* Determine if the given class needs to be included in the image according to the policy.
5759
*/
58-
public abstract boolean isClassIncluded(Class<?> cls);
60+
public boolean isClassIncluded(Class<?> cls) {
61+
Class<?> enclosingClass = cls.getEnclosingClass();
62+
return !Feature.class.isAssignableFrom(cls) && !AnnotationAccess.isAnnotationPresent(cls, TargetClass.class) && (enclosingClass == null || isClassIncluded(enclosingClass));
63+
}
5964

6065
/**
6166
* Determine if the given method needs to be included in the image according to the policy.
@@ -126,6 +131,9 @@ public LayeredBaseImageInclusionPolicy(Object reason) {
126131

127132
@Override
128133
public boolean isClassIncluded(Class<?> cls) {
134+
if (!super.isClassIncluded(cls)) {
135+
return false;
136+
}
129137
Class<?> enclosingClass = cls.getEnclosingClass();
130138
int classModifiers = cls.getModifiers();
131139
if (enclosingClass != null) {
@@ -172,11 +180,6 @@ public DefaultAllInclusionPolicy(Object reason) {
172180
super(reason);
173181
}
174182

175-
@Override
176-
public boolean isClassIncluded(Class<?> cls) {
177-
return true;
178-
}
179-
180183
@Override
181184
public void includeMethod(Executable method) {
182185
bb.postTask(debug -> bb.addRootMethod(method, false, reason));

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1231,8 +1231,11 @@ public enum ReportingMode {
12311231
@Option(help = "Include all classes, methods, fields, and resources from given paths", type = OptionType.Debug) //
12321232
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> IncludeAllFromPath = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());
12331233

1234+
@Option(help = "Include all classes, methods, fields, and resources from the class path", type = OptionType.Debug) //
1235+
public static final HostedOptionKey<Boolean> IncludeAllFromClassPath = new HostedOptionKey<>(false);
1236+
12341237
public static boolean includeAll() {
1235-
return IncludeAllFromModule.hasBeenSet() || IncludeAllFromPath.hasBeenSet();
1238+
return IncludeAllFromModule.hasBeenSet() || IncludeAllFromPath.hasBeenSet() || IncludeAllFromClassPath.hasBeenSet();
12361239
}
12371240

12381241
@Option(help = "Run layered image base layer open-world analysis. Includes all public types and methods that can be reached using normal Java access rules.")//

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ 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);
119+
boolean includeCurrent = classLoaderSupport.getJavaPathsToInclude().contains(classpathFile) || classLoaderSupport.includeAllFromClassPath();
120120
try {
121121
if (Files.isDirectory(classpathFile)) {
122122
scanDirectory(classpathFile, resourceCollector, includeCurrent);

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package com.oracle.svm.hosted;
2626

27+
import static com.oracle.svm.core.SubstrateOptions.IncludeAllFromClassPath;
2728
import static com.oracle.svm.core.SubstrateOptions.IncludeAllFromModule;
2829
import static com.oracle.svm.core.SubstrateOptions.IncludeAllFromPath;
2930
import static com.oracle.svm.core.util.VMError.guarantee;
@@ -77,8 +78,6 @@
7778
import org.graalvm.collections.EconomicSet;
7879
import org.graalvm.collections.MapCursor;
7980
import org.graalvm.collections.Pair;
80-
import jdk.graal.compiler.options.OptionKey;
81-
import jdk.graal.compiler.options.OptionValues;
8281
import org.graalvm.nativeimage.impl.AnnotationExtractor;
8382

8483
import com.oracle.svm.core.NativeImageClassLoaderOptions;
@@ -98,6 +97,8 @@
9897
import com.oracle.svm.util.ModuleSupport;
9998
import com.oracle.svm.util.ReflectionUtil;
10099

100+
import jdk.graal.compiler.options.OptionKey;
101+
import jdk.graal.compiler.options.OptionValues;
101102
import jdk.internal.module.Modules;
102103

103104
public class NativeImageClassLoaderSupport {
@@ -124,6 +125,7 @@ public class NativeImageClassLoaderSupport {
124125

125126
private Set<String> javaModuleNamesToInclude;
126127
private Set<Path> javaPathsToInclude;
128+
private boolean includeAllFromClassPath;
127129

128130
private final Set<Class<?>> classesToIncludeUnconditionally = Collections.newSetFromMap(new ConcurrentHashMap<>());
129131

@@ -239,6 +241,8 @@ public void loadAllClasses(ForkJoinPool executor, ImageClassLoader imageClassLoa
239241
.filter(p -> !classpath().contains(p))
240242
.findAny().ifPresent(p -> missingFromSetOfEntriesError(p, classpath(), "classpath", IncludeAllFromPath));
241243

244+
includeAllFromClassPath = IncludeAllFromClassPath.getValue(parsedHostedOptions);
245+
242246
new LoadClassHandler(executor, imageClassLoader).run();
243247
}
244248

@@ -705,7 +709,7 @@ private void initModule(ModuleReference moduleReference) {
705709
}
706710

707711
private void loadClassesFromPath(Path path) {
708-
final boolean includeUnconditionally = javaPathsToInclude.contains(path);
712+
final boolean includeUnconditionally = javaPathsToInclude.contains(path) || includeAllFromClassPath;
709713
if (ClasspathUtils.isJar(path)) {
710714
try {
711715
URI container = path.toAbsolutePath().toUri();
@@ -924,6 +928,10 @@ public Set<Path> getJavaPathsToInclude() {
924928
return javaPathsToInclude;
925929
}
926930

931+
public boolean includeAllFromClassPath() {
932+
return includeAllFromClassPath;
933+
}
934+
927935
public List<Class<?>> getClassesToIncludeUnconditionally() {
928936
return classesToIncludeUnconditionally.stream()
929937
.sorted(Comparator.comparing(Class::getTypeName))

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/NativeImagePointsToAnalysis.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,10 @@ public void onTypeReachable(AnalysisType type) {
141141
* Using getInstanceFields and getStaticFields allows to include the fields from the
142142
* substitution class.
143143
*/
144-
Stream.concat(Arrays.stream(type.getInstanceFields(true)), Arrays.stream(type.getStaticFields()))
144+
Stream.concat(Arrays.stream(getOrDefault(type, t -> t.getInstanceFields(true), new AnalysisField[0])),
145+
Arrays.stream(getOrDefault(type, AnalysisType::getStaticFields, new AnalysisField[0])))
145146
.map(OriginalFieldProvider::getJavaField)
146-
.filter(classInclusionPolicy::isFieldIncluded)
147+
.filter(field -> field != null && classInclusionPolicy.isFieldIncluded(field))
147148
.forEach(classInclusionPolicy::includeField);
148149
}
149150
});

0 commit comments

Comments
 (0)