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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
package com.oracle.graal.pointsto;

import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -350,17 +353,25 @@ public final boolean executorIsStarted() {

@Override
public void registerTypeForBaseImage(Class<?> cls) {
if (classInclusionPolicy.isClassIncluded(cls)) {
if (getOrDefault(cls, classInclusionPolicy::isClassIncluded, false)) {
classInclusionPolicy.includeClass(cls);
Stream.concat(Arrays.stream(cls.getDeclaredConstructors()), Arrays.stream(cls.getDeclaredMethods()))
Stream.concat(Arrays.stream(getOrDefault(cls, Class::getDeclaredConstructors, new Constructor<?>[0])), Arrays.stream(getOrDefault(cls, Class::getDeclaredMethods, new Method[0])))
.filter(classInclusionPolicy::isMethodIncluded)
.forEach(classInclusionPolicy::includeMethod);
Arrays.stream(cls.getDeclaredFields())
Arrays.stream(getOrDefault(cls, Class::getDeclaredFields, new Field[0]))
.filter(classInclusionPolicy::isFieldIncluded)
.forEach(classInclusionPolicy::includeField);
}
}

public static <T, U> U getOrDefault(T cls, Function<T, U> getMembers, U backup) {
try {
return getMembers.apply(cls);
} catch (NoClassDefFoundError | IncompatibleClassChangeError e) {
return backup;
}
}

/**
* Provide a non-null position. Some flows like newInstance and invoke require a non-null
* position, for others is just better. The constructed position is best-effort, i.e., it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
import java.lang.reflect.Modifier;

import org.graalvm.nativeimage.AnnotationAccess;
import org.graalvm.nativeimage.hosted.Feature;

import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.svm.core.annotate.TargetClass;

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

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

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

@Override
public boolean isClassIncluded(Class<?> cls) {
if (!super.isClassIncluded(cls)) {
return false;
}
Class<?> enclosingClass = cls.getEnclosingClass();
int classModifiers = cls.getModifiers();
if (enclosingClass != null) {
Expand Down Expand Up @@ -172,11 +180,6 @@ public DefaultAllInclusionPolicy(Object reason) {
super(reason);
}

@Override
public boolean isClassIncluded(Class<?> cls) {
return true;
}

@Override
public void includeMethod(Executable method) {
bb.postTask(debug -> bb.addRootMethod(method, false, reason));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1175,8 +1175,11 @@ public enum ReportingMode {
@Option(help = "Include all classes, methods, fields, and resources from given paths", type = OptionType.Debug) //
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> IncludeAllFromPath = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.build());

@Option(help = "Include all classes, methods, fields, and resources from the class path", type = OptionType.Debug) //
public static final HostedOptionKey<Boolean> IncludeAllFromClassPath = new HostedOptionKey<>(false);

public static boolean includeAll() {
return IncludeAllFromModule.hasBeenSet() || IncludeAllFromPath.hasBeenSet();
return IncludeAllFromModule.hasBeenSet() || IncludeAllFromPath.hasBeenSet() || IncludeAllFromClassPath.hasBeenSet();
}

@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.")//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void collectResources(ResourceCollector resourceCollector) {

/* Collect remaining resources from classpath */
classLoaderSupport.classpath().stream().parallel().forEach(classpathFile -> {
boolean includeCurrent = classLoaderSupport.getJavaPathsToInclude().contains(classpathFile);
boolean includeCurrent = classLoaderSupport.getJavaPathsToInclude().contains(classpathFile) || classLoaderSupport.includeAllFromClassPath();
try {
if (Files.isDirectory(classpathFile)) {
scanDirectory(classpathFile, resourceCollector, includeCurrent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.svm.hosted;

import static com.oracle.svm.core.SubstrateOptions.IncludeAllFromClassPath;
import static com.oracle.svm.core.SubstrateOptions.IncludeAllFromModule;
import static com.oracle.svm.core.SubstrateOptions.IncludeAllFromPath;
import static com.oracle.svm.core.util.VMError.guarantee;
Expand Down Expand Up @@ -77,8 +78,6 @@
import org.graalvm.collections.EconomicSet;
import org.graalvm.collections.MapCursor;
import org.graalvm.collections.Pair;
import jdk.graal.compiler.options.OptionKey;
import jdk.graal.compiler.options.OptionValues;
import org.graalvm.nativeimage.impl.AnnotationExtractor;

import com.oracle.svm.core.NativeImageClassLoaderOptions;
Expand All @@ -98,6 +97,8 @@
import com.oracle.svm.util.ModuleSupport;
import com.oracle.svm.util.ReflectionUtil;

import jdk.graal.compiler.options.OptionKey;
import jdk.graal.compiler.options.OptionValues;
import jdk.internal.module.Modules;

public class NativeImageClassLoaderSupport {
Expand All @@ -124,6 +125,7 @@ public class NativeImageClassLoaderSupport {

private Set<String> javaModuleNamesToInclude;
private Set<Path> javaPathsToInclude;
private boolean includeAllFromClassPath;

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

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

includeAllFromClassPath = IncludeAllFromClassPath.getValue(parsedHostedOptions);

new LoadClassHandler(executor, imageClassLoader).run();
}

Expand Down Expand Up @@ -705,7 +709,7 @@ private void initModule(ModuleReference moduleReference) {
}

private void loadClassesFromPath(Path path) {
final boolean includeUnconditionally = javaPathsToInclude.contains(path);
final boolean includeUnconditionally = javaPathsToInclude.contains(path) || includeAllFromClassPath;
if (ClasspathUtils.isJar(path)) {
try {
URI container = path.toAbsolutePath().toUri();
Expand Down Expand Up @@ -924,6 +928,10 @@ public Set<Path> getJavaPathsToInclude() {
return javaPathsToInclude;
}

public boolean includeAllFromClassPath() {
return includeAllFromClassPath;
}

public List<Class<?>> getClassesToIncludeUnconditionally() {
return classesToIncludeUnconditionally.stream()
.sorted(Comparator.comparing(Class::getTypeName))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,10 @@ public void onTypeReachable(AnalysisType type) {
* Using getInstanceFields and getStaticFields allows to include the fields from the
* substitution class.
*/
Stream.concat(Arrays.stream(type.getInstanceFields(true)), Arrays.stream(type.getStaticFields()))
Stream.concat(Arrays.stream(getOrDefault(type, t -> t.getInstanceFields(true), new AnalysisField[0])),
Arrays.stream(getOrDefault(type, AnalysisType::getStaticFields, new AnalysisField[0])))
.map(OriginalFieldProvider::getJavaField)
.filter(classInclusionPolicy::isFieldIncluded)
.filter(field -> field != null && classInclusionPolicy.isFieldIncluded(field))
.forEach(classInclusionPolicy::includeField);
}
});
Expand Down