Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GR-54953] Options to include all metadata from module or classpath entry #10180

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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 @@ -201,7 +201,7 @@ public static void registerAllDeclaredMethods(Class<?> declaringClass) {
* @since 23.0
*/
public static void registerAllConstructors(Class<?> declaringClass) {
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllConstructorsQuery(ConfigurationCondition.alwaysTrue(), true, declaringClass);
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllConstructorsQuery(ConfigurationCondition.alwaysTrue(), false, declaringClass);
}

/**
Expand All @@ -211,7 +211,7 @@ public static void registerAllConstructors(Class<?> declaringClass) {
* @since 23.0
*/
public static void registerAllDeclaredConstructors(Class<?> declaringClass) {
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredConstructorsQuery(ConfigurationCondition.alwaysTrue(), true, declaringClass);
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredConstructorsQuery(ConfigurationCondition.alwaysTrue(), false, declaringClass);
}

/**
Expand All @@ -221,7 +221,7 @@ public static void registerAllDeclaredConstructors(Class<?> declaringClass) {
* @since 23.0
*/
public static void registerAllFields(Class<?> declaringClass) {
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllFieldsQuery(ConfigurationCondition.alwaysTrue(), declaringClass);
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllFields(ConfigurationCondition.alwaysTrue(), declaringClass);
}

/**
Expand All @@ -231,7 +231,7 @@ public static void registerAllFields(Class<?> declaringClass) {
* @since 23.0
*/
public static void registerAllDeclaredFields(Class<?> declaringClass) {
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredFieldsQuery(ConfigurationCondition.alwaysTrue(), declaringClass);
ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredFields(ConfigurationCondition.alwaysTrue(), declaringClass);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.util.Arrays;

public interface ReflectionRegistry {
// TODO thread this true behind MRE flag
default void register(ConfigurationCondition condition, Class<?>... classes) {
Arrays.stream(classes).forEach(clazz -> register(condition, false, clazz));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ public interface RuntimeReflectionSupport extends ReflectionRegistry {

void registerAllDeclaredMethodsQuery(ConfigurationCondition condition, boolean queriedOnly, Class<?> clazz);

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

void registerAllDeclaredFieldsQuery(ConfigurationCondition condition, Class<?> clazz);
void registerAllDeclaredFields(ConfigurationCondition condition, Class<?> clazz);

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

Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ At runtime, premain runtime options are set along with main class' arguments in
* (GR-58914) `ActiveProcessorCount` must be set at isolate or VM creation time.
* (GR-59326) Ensure builder ForkJoin commonPool parallelism always respects NativeImageOptions.NumberOfThreads.
* (GR-60081) Native Image now targets `armv8.1-a` by default on AArch64. Use `-march=compatibility` for best compatibility or `-march=native` for best performance if the native executable is deployed on the same machine or on a machine with the same CPU features. To list all available machine types, use `-march=list`.
* (GR-54953) Add options `-H:IncludeAllMetadataForClassPathEntry`, `-H:+IncludeAllForClassPath`, and `-H:IncludeAllMetadataForModule` for bulk inclusion of reachability metadata.

## GraalVM for JDK 23 (Internal Version 24.1.0)
* (GR-51520) The old class initialization strategy, which was deprecated in GraalVM for JDK 22, is removed. The option `StrictImageHeap` no longer has any effect.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

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

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

Expand All @@ -54,12 +55,17 @@ public void setBigBang(BigBang bb) {
this.bb = bb;
}

public static boolean isClassIncludedBase(Class<?> cls) {
Class<?> enclosingClass = ReflectionUtil.linkageSafeQuery(cls, null, Class::getEnclosingClass);
return !Feature.class.isAssignableFrom(cls) && !AnnotationAccess.isAnnotationPresent(cls, TargetClass.class) && (enclosingClass == null || isClassIncludedBase(enclosingClass));
}

/**
* Determine if the given class needs to be included in the image according to the policy.
*/
public boolean isClassIncluded(Class<?> cls) {
Class<?> enclosingClass = cls.getEnclosingClass();
return !Feature.class.isAssignableFrom(cls) && !AnnotationAccess.isAnnotationPresent(cls, TargetClass.class) && (enclosingClass == null || isClassIncluded(enclosingClass));
return isClassIncludedBase(cls) && (enclosingClass == null || isClassIncluded(enclosingClass));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ public void onTypeInstantiated(AnalysisType type) {
/* Register the type as instantiated with all its super types. */

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

TypeState typeState = TypeState.forExactType(this, type, true);
TypeState typeStateNonNull = TypeState.forExactType(this, type, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public TypeResult<ConfigurationType> resolveType(UnresolvedConfigurationConditio
}

@Override
public void registerType(UnresolvedConfigurationCondition condition, ConfigurationType type) {
public void registerType(UnresolvedConfigurationCondition condition, ConfigurationType type, boolean registerMetadata) {
VMError.guarantee(condition.equals(type.getCondition()), "condition is already a part of the type");
configuration.add(type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1283,12 +1283,21 @@ public enum ReportingMode {
@Option(help = "Include all classes, methods, and fields from given modules", type = OptionType.Debug) //
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> IncludeAllFromModule = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());

@Option(help = "Include all classes, methods, fields, and resources from a given module for dynamic access", type = OptionType.Debug) //
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> EnableDynamicAccessForModule = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());

@Option(help = "Include all classes, methods, fields, and resources from given paths", type = OptionType.Debug) //
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> IncludeAllFromPath = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());

@Option(help = "Include all classes, methods, fields, and resources from given paths for dynamic access", type = OptionType.Debug) //
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> EnableDynamicAccessForClassPathEntry = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.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);

@Option(help = "Include all classes, methods, fields, and resources for dynamic access for the whole classpath", type = OptionType.Debug) //
public static final HostedOptionKey<Boolean> EnableDynamicAccess = new HostedOptionKey<>(false);

public static boolean includeAll() {
return IncludeAllFromModule.hasBeenSet() || IncludeAllFromPath.hasBeenSet() || IncludeAllFromClassPath.hasBeenSet();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ protected void parseClass(EconomicMap<String, Object> data) {

C queryCondition = isType ? conditionResolver.alwaysTrue() : condition;
T clazz = result.get();
delegate.registerType(conditionResult.get(), clazz);
delegate.registerType(conditionResult.get(), clazz, false);

registerIfNotDefault(data, false, clazz, "allDeclaredConstructors", () -> delegate.registerDeclaredConstructors(condition, false, clazz));
registerIfNotDefault(data, false, clazz, "allPublicConstructors", () -> delegate.registerPublicConstructors(condition, false, clazz));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public interface ReflectionConfigurationParserDelegate<C, T> {

TypeResult<T> resolveType(C condition, ConfigurationTypeDescriptor typeDescriptor, boolean allowPrimitives);

void registerType(C condition, T type);
void registerType(C condition, T type, boolean registerMetadata);

void registerPublicClasses(C condition, T type);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ protected void parseClass(EconomicMap<String, Object> data) {

C queryCondition = conditionResolver.alwaysTrue();
T clazz = result.get();
delegate.registerType(conditionResult.get(), clazz);
delegate.registerType(conditionResult.get(), clazz, true);

delegate.registerDeclaredClasses(queryCondition, clazz);
delegate.registerRecordComponents(queryCondition, clazz);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ public void collectResources(ResourceCollector resourceCollector) {

/* Collect remaining resources from classpath */
classLoaderSupport.classpath().stream().parallel().forEach(classpathFile -> {
boolean includeCurrent = classLoaderSupport.getJavaPathsToInclude().contains(classpathFile) || classLoaderSupport.includeAllFromClassPath();
boolean includeCurrent = classLoaderSupport.getPathsToInclude().contains(classpathFile) || classLoaderSupport.includeAllFromClassPath() ||
classLoaderSupport.getClassPathEntriesToEnableDynamicAccess().contains(classpathFile) || classLoaderSupport.isEnableDynamicAccessForClassPath();
try {
if (Files.isDirectory(classpathFile)) {
scanDirectory(classpathFile, resourceCollector, includeCurrent);
Expand All @@ -132,7 +133,8 @@ public void collectResources(ResourceCollector resourceCollector) {
private void collectResourceFromModule(ResourceCollector resourceCollector, ResourceLookupInfo info) {
ModuleReference moduleReference = info.resolvedModule.reference();
try (ModuleReader moduleReader = moduleReference.open()) {
boolean includeCurrent = classLoaderSupport.getJavaModuleNamesToInclude().contains(info.resolvedModule().name());
boolean includeCurrent = classLoaderSupport.getModuleNamesToInclude().contains(info.resolvedModule().name()) ||
classLoaderSupport.getModuleNamesToEnableDynamicAccess().contains(info.resolvedModule().name());
List<ConditionalResource> resourcesFound = new ArrayList<>();
moduleReader.list().forEach(resourceName -> {
var conditionsWithOrigins = shouldIncludeEntry(info.module, resourceCollector, resourceName, moduleReference.location().orElse(null), includeCurrent);
Expand Down
Loading
Loading