diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/Feature.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/Feature.java index 67430aefd108..40fb70adbf1f 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/Feature.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/Feature.java @@ -171,6 +171,14 @@ interface IsInConfigurationAccess extends FeatureAccess { */ @Platforms(Platform.HOSTED_ONLY.class) interface AfterRegistrationAccess extends FeatureAccess { + /** + * Creates access for runtime registration. All registrations should happen in + * {@link Feature#afterRegistration} + * + */ + ReflectionDynamicAccess createReflectionDynamicAccess(); + + ResourceDynamicAccess createResourceDynamicAccess(); } /** diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/InclusionCondition.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/InclusionCondition.java new file mode 100644 index 000000000000..5e2cb943982d --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/InclusionCondition.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.nativeimage.hosted; + +import org.graalvm.nativeimage.impl.TypeCondition; + +/** + * Condition that needs to be satisfied for inclusion of elements for runtime access. + * {@link InclusionCondition} is used with {@link ReflectionDynamicAccess} and + * {@link ResourceDynamicAccess} for programmatic registration of metadata. + *

+ * Currently, there is only two types of condition: typeReached and typeReachable(legacy) + *

  • typeReached (the default) that signifies that the type must be both reachable by + * static analysis at build time, and reached at run time. A type is reached at run time, right + * before the class-initialization routine starts for that type, or any of the type's subtypes are + * reached.
  • + *

    + * User can only create typeReached conditions, since typeReachable are + * deprecated. Conditions are created via {@link InclusionCondition#alwaysInclude} and + * {@link InclusionCondition#typeReached} factory methods. + */ +public interface InclusionCondition { + + /** + * Creates the type-reached condition that is always satisfied. Any element that is predicated + * with this condition will always be included. + * + * @return instance of the condition + */ + static InclusionCondition alwaysInclude() { + return TypeCondition.JAVA_LANG_OBJECT_REACHED; + } + + /** + * Creates the type-reached condition that is satisfied when the type is reached at runtime. + * + * @param type that has to be reached for this condition to be satisfied + * @return instance of the condition + */ + static InclusionCondition typeReached(Class type) { + return TypeCondition.create(type, true); + } +} diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/ReflectionDynamicAccess.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/ReflectionDynamicAccess.java new file mode 100644 index 000000000000..611f23997bac --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/ReflectionDynamicAccess.java @@ -0,0 +1,57 @@ +package org.graalvm.nativeimage.hosted; + +import java.lang.reflect.Executable; +import java.lang.reflect.Field; + +/** + * This class is used to register classes, methods, fields for reflection, serialization and JNI + * access at runtime. + * + * It should only be used at {@link Feature#afterRegistration}. + */ +public interface ReflectionDynamicAccess { + + /** + * Makes the provided classes available for reflection at runtime, and all of their accessible + * members available for reflection queries at run time. A call to {@link Class#forName} for the + * names of the classes will return the classes at run time. + * + * @param condition needs to be satisfied for inclusion of types for reflection at runtime + */ + void register(InclusionCondition condition, Class... classes); + + /** + * Makes the provided class available for reflection at runtime if {@code condition} is + * satisfied. A call to {@link Class#forName} for the name of the class will return the class + * (if it exists) or a {@link ClassNotFoundException} at run time. + */ + void registerClassLookup(InclusionCondition condition, String className); + + /** + * Makes the provided methods available for reflection at runtime if {@code condition} is + * satisfied. The methods will be returned by {@link Class#getMethod}, + * {@link Class#getDeclaredMethod(String, Class[])}, and all the other methods on {@link Class} + * that return a single method. Methods can be invoked via reflection. + */ + void register(InclusionCondition condition, Executable... methods); + + /** + * Makes the provided fields available for reflection at runtime if {@code condition} is + * satisfied.The fields will be returned by {@link Class#getField}, + * {@link Class#getDeclaredField(String)}, and all the other methods on {@link Class} that + * return a single field. Fields can be accessed via reflection + */ + void register(InclusionCondition condition, Field... fields); + + /** + * Makes the provided classes available for serialization and reflection at runtime if + * {@code condition} is satisfied. + */ + void registerForSerialization(InclusionCondition condition, Class... classes); + + /** + * Makes the provided classes available for JNI access at runtime if {@code condition} is + * satisfied. + */ + void registerForJNIAccess(InclusionCondition condition, Class... classes); +} diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/ResourceDynamicAccess.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/ResourceDynamicAccess.java new file mode 100644 index 000000000000..6cf928be6beb --- /dev/null +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/ResourceDynamicAccess.java @@ -0,0 +1,33 @@ +package org.graalvm.nativeimage.hosted; + +/** + * This class is used to register Java resources and ResourceBundles that should be accessible at + * runtime. + */ +public interface ResourceDynamicAccess { + + /** + * If {@code pattern} contains any wildcard patterns, such as star(*) or globstar(**), pattern + * is treated as glob pattern from {@code module} and will be registered if {@code condition} is + * satisfied. All resources that match the glob are available at runtime. Otherwise pattern + * represents Java resource from {@code module} that will be available at run time if + * {@code condition} is satisfied. + */ + void register(InclusionCondition condition, Module module, String pattern); + + default void register(InclusionCondition condition, String pattern) { + register(condition, null, pattern); + } + + /** + * Make Java ResourceBundle that is specified by a {@code bundleName} from module {@code module} + * available at run time if {@code condition} is satisfied. If the given {@code module} is + * unnamed, the ResourceBundle is looked up on the classpath instead. + */ + void registerResourceBundle(InclusionCondition condition, Module module, String bundleName); + + default void registerResourceBundle(InclusionCondition condition, String bundleName) { + registerResourceBundle(condition, null, bundleName); + } + +} diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeForeignAccess.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeForeignAccess.java index 2b5aa887f6ce..48dcc7c11c48 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeForeignAccess.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeForeignAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -46,7 +46,6 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeForeignAccessSupport; @Platforms(Platform.HOSTED_ONLY.class) @@ -68,7 +67,7 @@ public final class RuntimeForeignAccess { * @since 23.1 */ public static void registerForDowncall(Object desc, Object... options) { - ImageSingletons.lookup(RuntimeForeignAccessSupport.class).registerForDowncall(ConfigurationCondition.alwaysTrue(), desc, options); + ImageSingletons.lookup(RuntimeForeignAccessSupport.class).registerForDowncall(InclusionCondition.alwaysInclude(), desc, options); } /** @@ -86,7 +85,7 @@ public static void registerForDowncall(Object desc, Object... options) { * @since 24.1 */ public static void registerForUpcall(Object desc, Object... options) { - ImageSingletons.lookup(RuntimeForeignAccessSupport.class).registerForUpcall(ConfigurationCondition.alwaysTrue(), desc, options); + ImageSingletons.lookup(RuntimeForeignAccessSupport.class).registerForUpcall(InclusionCondition.alwaysInclude(), desc, options); } /** @@ -114,7 +113,7 @@ public static void registerForUpcall(Object desc, Object... options) { * @since 24.2 */ public static void registerForDirectUpcall(MethodHandle target, Object desc, Object... options) { - ImageSingletons.lookup(RuntimeForeignAccessSupport.class).registerForDirectUpcall(ConfigurationCondition.alwaysTrue(), target, desc, options); + ImageSingletons.lookup(RuntimeForeignAccessSupport.class).registerForDirectUpcall(InclusionCondition.alwaysInclude(), target, desc, options); } private RuntimeForeignAccess() { diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeJNIAccess.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeJNIAccess.java index e5c044517406..a9c2e4a3a090 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeJNIAccess.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeJNIAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -46,7 +46,6 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeJNIAccessSupport; /** @@ -66,7 +65,7 @@ public final class RuntimeJNIAccess { * @since 22.3 */ public static void register(Class... classes) { - ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(ConfigurationCondition.alwaysTrue(), classes); + ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(InclusionCondition.alwaysInclude(), classes); } /** @@ -79,7 +78,7 @@ public static void register(Class... classes) { * @since 22.3 */ public static void register(Executable... methods) { - ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(ConfigurationCondition.alwaysTrue(), false, methods); + ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(InclusionCondition.alwaysInclude(), false, methods); } /** @@ -92,7 +91,7 @@ public static void register(Executable... methods) { * @since 22.3 */ public static void register(Field... fields) { - ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(ConfigurationCondition.alwaysTrue(), false, fields); + ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(InclusionCondition.alwaysInclude(), false, fields); } private RuntimeJNIAccess() { diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeProxyCreation.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeProxyCreation.java index a2f4f7bb781e..d141b2af7399 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeProxyCreation.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeProxyCreation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -43,7 +43,6 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeProxyCreationSupport; /** @@ -62,7 +61,7 @@ public final class RuntimeProxyCreation { * @since 22.3 */ public static void register(Class... interfaces) { - ImageSingletons.lookup(RuntimeProxyCreationSupport.class).addProxyClass(ConfigurationCondition.alwaysTrue(), interfaces); + ImageSingletons.lookup(RuntimeProxyCreationSupport.class).addProxyClass(InclusionCondition.alwaysInclude(), interfaces); } private RuntimeProxyCreation() { diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeReflection.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeReflection.java index a4b5adb949f3..72316c14cfef 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeReflection.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeReflection.java @@ -48,7 +48,6 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; //Checkstyle: allow reflection @@ -69,7 +68,7 @@ public final class RuntimeReflection { * @since 19.0 */ public static void register(Class... classes) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).register(ConfigurationCondition.alwaysTrue(), classes); + ImageSingletons.lookup(RuntimeReflectionSupport.class).register(InclusionCondition.alwaysInclude(), classes); } /** @@ -80,7 +79,7 @@ public static void register(Class... classes) { * @since 23.0 */ public static void registerClassLookup(String className) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerClassLookup(ConfigurationCondition.alwaysTrue(), className); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerClassLookup(InclusionCondition.alwaysInclude(), className); } /** @@ -91,7 +90,7 @@ public static void registerClassLookup(String className) { * @since 19.0 */ public static void register(Executable... methods) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).register(ConfigurationCondition.alwaysTrue(), false, methods); + ImageSingletons.lookup(RuntimeReflectionSupport.class).register(InclusionCondition.alwaysInclude(), false, methods); } /** @@ -103,7 +102,7 @@ public static void register(Executable... methods) { * @since 21.3 */ public static void registerAsQueried(Executable... methods) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).register(ConfigurationCondition.alwaysTrue(), true, methods); + ImageSingletons.lookup(RuntimeReflectionSupport.class).register(InclusionCondition.alwaysInclude(), true, methods); } /** @@ -116,7 +115,7 @@ public static void registerAsQueried(Executable... methods) { * @since 23.0 */ public static void registerMethodLookup(Class declaringClass, String methodName, Class... parameterTypes) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerMethodLookup(ConfigurationCondition.alwaysTrue(), declaringClass, methodName, parameterTypes); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerMethodLookup(InclusionCondition.alwaysInclude(), declaringClass, methodName, parameterTypes); } /** @@ -130,7 +129,7 @@ public static void registerMethodLookup(Class declaringClass, String methodNa * @since 23.0 */ public static void registerConstructorLookup(Class declaringClass, Class... parameterTypes) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerConstructorLookup(ConfigurationCondition.alwaysTrue(), declaringClass, parameterTypes); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerConstructorLookup(InclusionCondition.alwaysInclude(), declaringClass, parameterTypes); } /** @@ -141,7 +140,7 @@ public static void registerConstructorLookup(Class declaringClass, Class.. * @since 19.0 */ public static void register(Field... fields) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).register(ConfigurationCondition.alwaysTrue(), false, fields); + ImageSingletons.lookup(RuntimeReflectionSupport.class).register(InclusionCondition.alwaysInclude(), false, fields); } /** @@ -153,7 +152,7 @@ public static void register(Field... fields) { * @since 19.0 */ public static void registerFieldLookup(Class declaringClass, String fieldName) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerFieldLookup(ConfigurationCondition.alwaysTrue(), declaringClass, fieldName); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerFieldLookup(InclusionCondition.alwaysInclude(), declaringClass, fieldName); } /** @@ -162,7 +161,7 @@ public static void registerFieldLookup(Class declaringClass, String fieldName * @since 23.0 */ public static void registerAllClasses(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllClassesQuery(ConfigurationCondition.alwaysTrue(), declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllClassesQuery(InclusionCondition.alwaysInclude(), declaringClass); } /** @@ -171,7 +170,7 @@ public static void registerAllClasses(Class declaringClass) { * @since 23.0 */ public static void registerAllDeclaredClasses(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredClassesQuery(ConfigurationCondition.alwaysTrue(), declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredClassesQuery(InclusionCondition.alwaysInclude(), declaringClass); } /** @@ -181,7 +180,7 @@ public static void registerAllDeclaredClasses(Class declaringClass) { * @since 23.0 */ public static void registerAllMethods(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllMethodsQuery(ConfigurationCondition.alwaysTrue(), true, declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllMethodsQuery(InclusionCondition.alwaysInclude(), true, declaringClass); } /** @@ -191,7 +190,7 @@ public static void registerAllMethods(Class declaringClass) { * @since 23.0 */ public static void registerAllDeclaredMethods(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredMethodsQuery(ConfigurationCondition.alwaysTrue(), true, declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredMethodsQuery(InclusionCondition.alwaysInclude(), true, declaringClass); } /** @@ -201,7 +200,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(InclusionCondition.alwaysInclude(), true, declaringClass); } /** @@ -211,7 +210,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(InclusionCondition.alwaysInclude(), true, declaringClass); } /** @@ -221,7 +220,7 @@ public static void registerAllDeclaredConstructors(Class declaringClass) { * @since 23.0 */ public static void registerAllFields(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllFields(ConfigurationCondition.alwaysTrue(), declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllFields(InclusionCondition.alwaysInclude(), declaringClass); } /** @@ -231,7 +230,7 @@ public static void registerAllFields(Class declaringClass) { * @since 23.0 */ public static void registerAllDeclaredFields(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredFields(ConfigurationCondition.alwaysTrue(), declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredFields(InclusionCondition.alwaysInclude(), declaringClass); } /** @@ -240,7 +239,7 @@ public static void registerAllDeclaredFields(Class declaringClass) { * @since 23.0 */ public static void registerAllNestMembers(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllNestMembersQuery(ConfigurationCondition.alwaysTrue(), declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllNestMembersQuery(InclusionCondition.alwaysInclude(), declaringClass); } /** @@ -249,7 +248,7 @@ public static void registerAllNestMembers(Class declaringClass) { * @since 23.0 */ public static void registerAllPermittedSubclasses(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllPermittedSubclassesQuery(ConfigurationCondition.alwaysTrue(), declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllPermittedSubclassesQuery(InclusionCondition.alwaysInclude(), declaringClass); } /** @@ -258,7 +257,7 @@ public static void registerAllPermittedSubclasses(Class declaringClass) { * @since 23.0 */ public static void registerAllRecordComponents(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllRecordComponentsQuery(ConfigurationCondition.alwaysTrue(), declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllRecordComponentsQuery(InclusionCondition.alwaysInclude(), declaringClass); } /** @@ -267,7 +266,7 @@ public static void registerAllRecordComponents(Class declaringClass) { * @since 23.0 */ public static void registerAllSigners(Class declaringClass) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllSignersQuery(ConfigurationCondition.alwaysTrue(), declaringClass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllSignersQuery(InclusionCondition.alwaysInclude(), declaringClass); } /** diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java index 6d7b6cd60398..c55cab1d968c 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -47,7 +47,6 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeResourceSupport; /** @@ -84,7 +83,7 @@ public static void addResource(Module module, String resourcePath, byte[] resour Objects.requireNonNull(resourcePath); Objects.requireNonNull(resourceContent); ImageSingletons.lookup(RuntimeResourceSupport.class).injectResource(module, resourcePath, resourceContent, "Manually added via RuntimeResourceAccess"); - ImageSingletons.lookup(RuntimeResourceSupport.class).addCondition(ConfigurationCondition.alwaysTrue(), module, resourcePath); + ImageSingletons.lookup(RuntimeResourceSupport.class).addCondition(InclusionCondition.alwaysInclude(), module, resourcePath); } /** @@ -96,7 +95,7 @@ public static void addResource(Module module, String resourcePath, byte[] resour */ public static void addResourceBundle(Module module, String baseBundleName, Locale[] locales) { Objects.requireNonNull(locales); - RuntimeResourceSupport.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), + RuntimeResourceSupport.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), withModuleName(module, baseBundleName), Arrays.asList(locales)); } @@ -108,7 +107,7 @@ public static void addResourceBundle(Module module, String baseBundleName, Local * @since 22.3 */ public static void addResourceBundle(Module module, String bundleName) { - RuntimeResourceSupport.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), + RuntimeResourceSupport.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), withModuleName(module, bundleName)); } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeSerialization.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeSerialization.java index 8de8de2ea716..7b1d506ca951 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeSerialization.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeSerialization.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -42,7 +42,6 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; /** @@ -72,7 +71,7 @@ public final class RuntimeSerialization { * @since 21.3 */ public static void registerIncludingAssociatedClasses(Class clazz) { - RuntimeSerializationSupport.singleton().registerIncludingAssociatedClasses(ConfigurationCondition.alwaysTrue(), clazz); + RuntimeSerializationSupport.singleton().registerIncludingAssociatedClasses(InclusionCondition.alwaysInclude(), clazz); } /** @@ -82,7 +81,7 @@ public static void registerIncludingAssociatedClasses(Class clazz) { */ public static void register(Class... classes) { for (Class clazz : classes) { - RuntimeSerializationSupport.singleton().register(ConfigurationCondition.alwaysTrue(), clazz); + RuntimeSerializationSupport.singleton().register(InclusionCondition.alwaysInclude(), clazz); } } @@ -103,7 +102,7 @@ public static void register(Class... classes) { @Deprecated(since = "24.2") @SuppressWarnings("unused") public static void registerWithTargetConstructorClass(Class clazz, Class customTargetConstructorClazz) { - RuntimeSerializationSupport.singleton().register(ConfigurationCondition.alwaysTrue(), clazz); + RuntimeSerializationSupport.singleton().register(InclusionCondition.alwaysInclude(), clazz); } /** @@ -114,7 +113,7 @@ public static void registerWithTargetConstructorClass(Class clazz, Class c * @since 22.3 */ public static void registerLambdaCapturingClass(Class lambdaCapturingClass) { - RuntimeSerializationSupport.singleton().registerLambdaCapturingClass(ConfigurationCondition.alwaysTrue(), lambdaCapturingClass); + RuntimeSerializationSupport.singleton().registerLambdaCapturingClass(InclusionCondition.alwaysInclude(), lambdaCapturingClass); } /** @@ -125,7 +124,7 @@ public static void registerLambdaCapturingClass(Class lambdaCapturingClass) { * @since 22.3 */ public static void registerProxyClass(Class... implementedInterfaces) { - RuntimeSerializationSupport.singleton().registerProxyClass(ConfigurationCondition.alwaysTrue(), implementedInterfaces); + RuntimeSerializationSupport.singleton().registerProxyClass(InclusionCondition.alwaysInclude(), implementedInterfaces); } private RuntimeSerialization() { diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ReflectionRegistry.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ReflectionRegistry.java index 9d0534347cfb..ca5515207991 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ReflectionRegistry.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ReflectionRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -44,22 +44,24 @@ import java.lang.reflect.Field; import java.util.Arrays; +import org.graalvm.nativeimage.hosted.InclusionCondition; + public interface ReflectionRegistry { - default void register(ConfigurationCondition condition, Class... classes) { + default void register(InclusionCondition condition, Class... classes) { Arrays.stream(classes).forEach(clazz -> register(condition, false, clazz)); } - void register(ConfigurationCondition condition, boolean unsafeAllocated, Class clazz); + void register(InclusionCondition condition, boolean unsafeAllocated, Class clazz); - void register(ConfigurationCondition condition, boolean queriedOnly, Executable... methods); + void register(InclusionCondition condition, boolean queriedOnly, Executable... methods); - void register(ConfigurationCondition condition, boolean finalIsWritable, Field... fields); + void register(InclusionCondition condition, boolean finalIsWritable, Field... fields); - void registerClassLookup(ConfigurationCondition condition, String typeName); + void registerClassLookup(InclusionCondition condition, String typeName); - void registerFieldLookup(ConfigurationCondition condition, Class declaringClass, String fieldName); + void registerFieldLookup(InclusionCondition condition, Class declaringClass, String fieldName); - void registerMethodLookup(ConfigurationCondition condition, Class declaringClass, String methodName, Class... parameterTypes); + void registerMethodLookup(InclusionCondition condition, Class declaringClass, String methodName, Class... parameterTypes); - void registerConstructorLookup(ConfigurationCondition condition, Class declaringClass, Class... parameterTypes); + void registerConstructorLookup(InclusionCondition condition, Class declaringClass, Class... parameterTypes); } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeForeignAccessSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeForeignAccessSupport.java index dd0537c496fc..28e1a879ebe9 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeForeignAccessSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeForeignAccessSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -42,10 +42,12 @@ import java.lang.invoke.MethodHandle; +import org.graalvm.nativeimage.hosted.InclusionCondition; + public interface RuntimeForeignAccessSupport { - void registerForDowncall(ConfigurationCondition condition, Object desc, Object... options); + void registerForDowncall(InclusionCondition condition, Object desc, Object... options); - void registerForUpcall(ConfigurationCondition condition, Object desc, Object... options); + void registerForUpcall(InclusionCondition condition, Object desc, Object... options); - void registerForDirectUpcall(ConfigurationCondition condition, MethodHandle target, Object desc, Object... options); + void registerForDirectUpcall(InclusionCondition condition, MethodHandle target, Object desc, Object... options); } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeProxyCreationSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeProxyCreationSupport.java index f7ca149c3c3f..1eb506f9ff2a 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeProxyCreationSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeProxyCreationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -40,6 +40,8 @@ */ package org.graalvm.nativeimage.impl; +import org.graalvm.nativeimage.hosted.InclusionCondition; + public interface RuntimeProxyCreationSupport { - void addProxyClass(ConfigurationCondition condition, Class... interfaces); + void addProxyClass(InclusionCondition condition, Class... interfaces); } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java index 8d1d11c169e3..a0f2459868d7 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeReflectionSupport.java @@ -44,38 +44,43 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeJNIAccess; import org.graalvm.nativeimage.hosted.RuntimeProxyCreation; public interface RuntimeReflectionSupport extends ReflectionRegistry { // needed as reflection-specific ImageSingletons key - void registerAllMethodsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz); + void registerAllMethodsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz); - void registerAllDeclaredMethodsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz); + void registerAllDeclaredMethodsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz); - void registerAllFields(ConfigurationCondition condition, Class clazz); + void registerAllFields(InclusionCondition condition, Class clazz); - void registerAllDeclaredFields(ConfigurationCondition condition, Class clazz); + void registerAllFieldsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz); - void registerAllConstructorsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz); + void registerAllDeclaredFields(InclusionCondition condition, Class clazz); - void registerAllDeclaredConstructorsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz); + void registerAllDeclaredFieldsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz); - void registerAllClassesQuery(ConfigurationCondition condition, Class clazz); + void registerAllConstructorsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz); - void registerAllDeclaredClassesQuery(ConfigurationCondition condition, Class clazz); + void registerAllDeclaredConstructorsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz); - void registerAllRecordComponentsQuery(ConfigurationCondition condition, Class clazz); + void registerAllClassesQuery(InclusionCondition condition, Class clazz); - void registerAllPermittedSubclassesQuery(ConfigurationCondition condition, Class clazz); + void registerAllDeclaredClassesQuery(InclusionCondition condition, Class clazz); - void registerAllNestMembersQuery(ConfigurationCondition condition, Class clazz); + void registerAllRecordComponentsQuery(InclusionCondition condition, Class clazz); - void registerAllSignersQuery(ConfigurationCondition condition, Class clazz); + void registerAllPermittedSubclassesQuery(InclusionCondition condition, Class clazz); - void registerClassLookupException(ConfigurationCondition condition, String typeName, Throwable t); + void registerAllNestMembersQuery(InclusionCondition condition, Class clazz); - default void registerClassFully(ConfigurationCondition condition, Class clazz) { + void registerAllSignersQuery(InclusionCondition condition, Class clazz); + + void registerClassLookupException(InclusionCondition condition, String typeName, Throwable t); + + default void registerClassFully(InclusionCondition condition, Class clazz) { register(condition, false, clazz); // GR-62143 Register all fields is very slow. diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java index f0c2273cbf95..c51570a08924 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -44,11 +44,12 @@ import java.util.Locale; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.InclusionCondition; public interface RuntimeResourceSupport { @SuppressWarnings("unchecked") - static RuntimeResourceSupport singleton() { + static RuntimeResourceSupport singleton() { return ImageSingletons.lookup(RuntimeResourceSupport.class); } @@ -63,15 +64,15 @@ static RuntimeResourceSupport singleton() { void addResourceBundles(C condition, String basename, Collection locales); /* Following functions are used only from features */ - void addCondition(ConfigurationCondition configurationCondition, Module module, String resourcePath); + void addCondition(InclusionCondition metadataCondition1, Module module, String resourcePath); void addResourceEntry(Module module, String resourcePath, Object origin); default void addResource(Module module, String resourcePath, Object origin) { - addResource(ConfigurationCondition.alwaysTrue(), module, resourcePath, origin); + addResource(InclusionCondition.alwaysInclude(), module, resourcePath, origin); } - default void addResource(ConfigurationCondition condition, Module module, String resourcePath, Object origin) { + default void addResource(InclusionCondition condition, Module module, String resourcePath, Object origin) { addResourceEntry(module, resourcePath, origin); addCondition(condition, module, resourcePath); } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeSerializationSupport.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeSerializationSupport.java index 3237047e86d8..81cb4eaae0e7 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeSerializationSupport.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeSerializationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -45,16 +45,21 @@ import java.util.stream.Collectors; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.InclusionCondition; public interface RuntimeSerializationSupport { @SuppressWarnings("unchecked") - static RuntimeSerializationSupport singleton() { + static RuntimeSerializationSupport singleton() { return ImageSingletons.lookup(RuntimeSerializationSupport.class); } void registerIncludingAssociatedClasses(C condition, Class clazz); + default void register(C condition, Class... classes) { + Arrays.stream(classes).forEach(clazz -> register(condition, clazz)); + } + void register(C condition, Class clazz); void register(C condition, String clazz); diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ConfigurationCondition.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/TypeCondition.java similarity index 63% rename from sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ConfigurationCondition.java rename to sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/TypeCondition.java index d7c56dc0dd98..9ac5fcc25201 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ConfigurationCondition.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/TypeCondition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -42,44 +42,20 @@ import java.util.Objects; +import org.graalvm.nativeimage.hosted.InclusionCondition; + /** - * A condition that describes if a reflectively-accessed element in Native Image is visible by the - * user at run time. - *

    - * Currently, there is only two types of condition: - *

  • typeReached (the default) that signifies that the type must be both reachable by - * static analysis at build time, and reached at run time. A type is reached at run time, right - * before the class-initialization routine starts for that type, or any of the type's subtypes are - * reached.
  • - *
  • typeReachable (legacy) that signifies that the type must be reachable by static - * analysis at build time.
  • - *

    - * When {@link ConfigurationCondition#runtimeChecked} is true denotes that this is a + * Type that represents both type-reached and type-reachable condition. When + * {@link TypeCondition#runtimeChecked} is true denotes that this is a * typeReached condition. */ -public final class ConfigurationCondition { +public class TypeCondition implements InclusionCondition { /* Cached to save space: it is used as a marker for all non-conditional elements */ - private static final ConfigurationCondition JAVA_LANG_OBJECT_REACHED = new ConfigurationCondition(Object.class, true); - - public static ConfigurationCondition alwaysTrue() { - return JAVA_LANG_OBJECT_REACHED; - } - + public static final TypeCondition JAVA_LANG_OBJECT_REACHED = new TypeCondition(Object.class, true); private final Class type; - private final boolean runtimeChecked; - - /** - * Creates the default type-reached condition that is satisfied when the type is reached at - * runtime. - * - * @param type that has to be reached for this condition to be satisfied - * @return instance of the condition - */ - public static ConfigurationCondition create(Class type) { - return create(type, true); - } + final boolean runtimeChecked; /** * Creates either a type-reached condition ({@code runtimeChecked = true}) or a type-reachable @@ -89,31 +65,28 @@ public static ConfigurationCondition create(Class type) { * @param runtimeChecked makes this a type-reachable condition when false * @return instance of the condition */ - public static ConfigurationCondition create(Class type, boolean runtimeChecked) { + + public static TypeCondition create(Class type, boolean runtimeChecked) { Objects.requireNonNull(type); - if (JAVA_LANG_OBJECT_REACHED.getType().equals(type)) { - return JAVA_LANG_OBJECT_REACHED; + if (TypeCondition.JAVA_LANG_OBJECT_REACHED.getKey().equals(type)) { + return TypeCondition.JAVA_LANG_OBJECT_REACHED; } - return new ConfigurationCondition(type, runtimeChecked); + return new TypeCondition(type, runtimeChecked); } public boolean isAlwaysTrue() { - return ConfigurationCondition.alwaysTrue().equals(this); + return InclusionCondition.alwaysInclude().equals(this); } - private ConfigurationCondition(Class type, boolean runtimeChecked) { + public TypeCondition(Class type, boolean runtimeChecked) { this.runtimeChecked = runtimeChecked; this.type = type; } - public Class getType() { + public Class getKey() { return type; } - public boolean isRuntimeChecked() { - return runtimeChecked; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -122,7 +95,7 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - ConfigurationCondition that = (ConfigurationCondition) o; + TypeCondition that = (TypeCondition) o; return runtimeChecked == that.runtimeChecked && Objects.equals(type, that.type); } @@ -138,4 +111,8 @@ public String toString() { ", runtimeChecked=" + runtimeChecked + ')'; } + + public boolean isRuntimeChecked() { + return runtimeChecked; + } } diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/UnresolvedConfigurationCondition.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/UnresolvedConfigurationCondition.java index fb7a182cda99..509f1115c172 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/UnresolvedConfigurationCondition.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/UnresolvedConfigurationCondition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -42,9 +42,11 @@ import java.util.Objects; +import org.graalvm.nativeimage.hosted.InclusionCondition; + /** - * Represents a {@link ConfigurationCondition} during parsing before it is resolved in a context of - * the classpath. + * Represents a {@link InclusionCondition} during parsing before it is resolved in a context of the + * classpath. */ public final class UnresolvedConfigurationCondition implements Comparable { private static final UnresolvedConfigurationCondition JAVA_LANG_OBJECT_REACHED = new UnresolvedConfigurationCondition(Object.class.getTypeName(), true); diff --git a/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java b/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java index 7af57c99b3f6..76626d9474fe 100644 --- a/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java +++ b/substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java @@ -34,7 +34,7 @@ import java.util.List; import java.util.Locale; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; import org.junit.Assert; import org.junit.Test; @@ -127,7 +127,7 @@ public void addResourceBundles(UnresolvedConfigurationCondition condition, Strin } @Override - public void addCondition(ConfigurationCondition configurationCondition, Module module, String resourcePath) { + public void addCondition(InclusionCondition configurationCondition, Module module, String resourcePath) { } diff --git a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourcesRegistry.java b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourcesRegistry.java index 5fbdb3418524..4bb812187298 100644 --- a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourcesRegistry.java +++ b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourcesRegistry.java @@ -28,13 +28,13 @@ import java.util.Locale; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.RuntimeResourceSupport; public interface ResourcesRegistry extends RuntimeResourceSupport { @SuppressWarnings("unchecked") - static ResourcesRegistry singleton() { + static ResourcesRegistry singleton() { return ImageSingletons.lookup(ResourcesRegistry.class); } diff --git a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java index 61c884918041..e549c54226ee 100644 --- a/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java +++ b/substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java @@ -40,7 +40,7 @@ import java.util.concurrent.ConcurrentMap; import java.util.regex.Pattern; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; import com.oracle.svm.configure.ConditionalElement; @@ -82,7 +82,7 @@ public void addResourceEntry(Module module, String resourcePath, Object origin) } @Override - public void addCondition(ConfigurationCondition condition, Module module, String resourcePath) { + public void addCondition(InclusionCondition condition, Module module, String resourcePath) { throw new UnsupportedOperationException("Unused function."); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ClassLoaderSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ClassLoaderSupport.java index 3f3a411b3a13..1bd93786ae24 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ClassLoaderSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ClassLoaderSupport.java @@ -34,7 +34,7 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; @Platforms(Platform.HOSTED_ONLY.class) public abstract class ClassLoaderSupport { @@ -52,7 +52,7 @@ public boolean isNativeImageClassLoader(ClassLoader classLoader) { protected abstract boolean isNativeImageClassLoaderImpl(ClassLoader classLoader); - public record ConditionWithOrigin(ConfigurationCondition condition, Object origin) { + public record ConditionWithOrigin(InclusionCondition condition, Object origin) { } public interface ResourceCollector { @@ -60,7 +60,7 @@ public interface ResourceCollector { void addResourceEntry(Module module, String resourceName, Object origin); - void addResourceConditionally(Module module, String resourceName, ConfigurationCondition condition, Object origin); + void addResourceConditionally(Module module, String resourceName, InclusionCondition condition, Object origin); void registerNegativeQuery(Module module, String resourceName); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/RuntimeConditionSet.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/RuntimeConditionSet.java index d403da2152bc..917e005ee97c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/RuntimeConditionSet.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/RuntimeConditionSet.java @@ -33,7 +33,8 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; +import org.graalvm.nativeimage.impl.TypeCondition; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.util.VMError; @@ -44,7 +45,7 @@ *

    * If any of the {@link #conditions} is satisfied then the whole set becomes also * {@link #satisfied}. {@link RuntimeConditionSet}s can be created at build time - * {@link #createHosted(ConfigurationCondition)} and stored to the image heap, or it can be encoded + * {@link #createHosted(InclusionCondition)} and stored to the image heap, or it can be encoded * ({@link #getTypesForEncoding()} and later decoded at run time ({@link #createDecoded(Object[])}. * The current implementation does not cache {@link #conditions}, although this will be implemented * in the future (GR-49526) @@ -60,18 +61,18 @@ public static RuntimeConditionSet emptySet() { } @Platforms(Platform.HOSTED_ONLY.class) - public static RuntimeConditionSet createHosted(ConfigurationCondition condition) { + public static RuntimeConditionSet createHosted(InclusionCondition condition) { var conditionSet = new RuntimeConditionSet(new Object[0]); conditionSet.addCondition(condition); return conditionSet; } @Platforms(Platform.HOSTED_ONLY.class) - public synchronized void addCondition(ConfigurationCondition cnd) { - VMError.guarantee(cnd.isRuntimeChecked(), "Only runtime conditions can be added to the ConditionalRuntimeValue."); + public synchronized void addCondition(InclusionCondition cnd) { + VMError.guarantee(((TypeCondition) cnd).isRuntimeChecked(), "Only runtime conditions can be added to the ConditionalRuntimeValue."); if (satisfied) { return; - } else if (cnd.isAlwaysTrue()) { + } else if (((TypeCondition) cnd).isAlwaysTrue()) { conditions = null; satisfied = true; return; @@ -159,11 +160,11 @@ private void setConditions(Object[] conditions) { satisfied = false; } - private static Object createRuntimeCondition(ConfigurationCondition cnd) { - if (cnd.isAlwaysTrue() || !cnd.isRuntimeChecked()) { + private static Object createRuntimeCondition(InclusionCondition cnd) { + if (((TypeCondition) cnd).isAlwaysTrue() || !((TypeCondition) cnd).isRuntimeChecked()) { throw VMError.shouldNotReachHere("We should never create run-time conditions from conditions that are always true at build time. Condition: " + cnd); } - return cnd.getType(); + return ((TypeCondition) cnd).getKey(); } private static boolean isSatisfied(Object condition) { @@ -190,7 +191,7 @@ private UnmodifiableRuntimeConditionSet(Object[] conditions) { } @Override - public synchronized void addCondition(ConfigurationCondition cnd) { + public synchronized void addCondition(InclusionCondition cnd) { throw new UnsupportedOperationException("Can't add conditions to an unmodifiable set of conditions."); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java index a7818355e12e..97cea27de0ee 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java @@ -29,12 +29,15 @@ import java.lang.reflect.Modifier; import java.util.EnumSet; import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platform.HOSTED_ONLY; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import com.oracle.svm.core.configure.ConditionalRuntimeValue; import com.oracle.svm.core.configure.RuntimeConditionSet; @@ -78,11 +81,11 @@ private static ClassForNameSupport[] layeredSingletons() { @Platforms(Platform.HOSTED_ONLY.class) public void registerClass(Class clazz) { - registerClass(ConfigurationCondition.alwaysTrue(), clazz); + registerClass(InclusionCondition.alwaysInclude(), clazz); } @Platforms(Platform.HOSTED_ONLY.class) - public void registerClass(ConfigurationCondition condition, Class clazz) { + public void registerClass(InclusionCondition condition, Class clazz) { assert !clazz.isPrimitive() : "primitive classes cannot be looked up by name"; if (PredefinedClassesSupport.isPredefined(clazz)) { return; // must be defined at runtime before it can be looked up @@ -134,7 +137,7 @@ private boolean isLibGraalClass(Class clazz) { } public static ConditionalRuntimeValue updateConditionalValue(ConditionalRuntimeValue existingConditionalValue, Object newValue, - ConfigurationCondition additionalCondition) { + InclusionCondition additionalCondition) { if (existingConditionalValue == null) { return new ConditionalRuntimeValue<>(RuntimeConditionSet.createHosted(additionalCondition), newValue); } else { @@ -145,12 +148,12 @@ public static ConditionalRuntimeValue updateConditionalValue(Conditional } @Platforms(Platform.HOSTED_ONLY.class) - public void registerExceptionForClass(ConfigurationCondition condition, String className, Throwable t) { + public void registerExceptionForClass(InclusionCondition condition, String className, Throwable t) { updateCondition(condition, className, t); } @Platforms(Platform.HOSTED_ONLY.class) - public void registerNegativeQuery(ConfigurationCondition condition, String className) { + public void registerNegativeQuery(InclusionCondition condition, String className) { /* * If the class is not accessible by the builder class loader, but was already registered * through registerClass(Class), we don't overwrite the actual class or exception. @@ -159,7 +162,7 @@ public void registerNegativeQuery(ConfigurationCondition condition, String class } @Platforms(Platform.HOSTED_ONLY.class) - public void registerUnsafeAllocated(ConfigurationCondition condition, Class clazz) { + public void registerUnsafeAllocated(InclusionCondition condition, Class clazz) { if (!clazz.isArray() && !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { /* Otherwise, UNSAFE.allocateInstance results in InstantiationException */ var conditionSet = unsafeInstantiatedClasses.putIfAbsent(clazz, RuntimeConditionSet.createHosted(condition)); @@ -169,7 +172,7 @@ public void registerUnsafeAllocated(ConfigurationCondition condition, Class c } } - private void updateCondition(ConfigurationCondition condition, String className, Object value) { + private void updateCondition(InclusionCondition condition, String className, Object value) { synchronized (knownClasses) { var runtimeConditions = knownClasses.putIfAbsent(className, new ConditionalRuntimeValue<>(RuntimeConditionSet.createHosted(condition), value)); if (runtimeConditions != null) { @@ -251,6 +254,11 @@ public int count() { return knownClasses.size(); } + public Set getKnownClasses() { + return StreamSupport.stream(knownClasses.getKeys().spliterator(), false) + .collect(Collectors.toSet()); + } + public static RuntimeConditionSet getConditionFor(Class jClass) { Objects.requireNonNull(jClass); String jClassName = jClass.getName(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaNetHttpFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaNetHttpFeature.java index a36b46ba346c..c14cf9349935 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaNetHttpFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaNetHttpFeature.java @@ -27,8 +27,8 @@ import java.util.Optional; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import com.oracle.svm.configure.ResourcesRegistry; @@ -94,7 +94,7 @@ public void afterRegistration(AfterRegistrationAccess access) { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { access.registerReachabilityHandler(a -> { - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "sun.net.httpserver.simpleserver.resources.simpleserver"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "sun.net.httpserver.simpleserver.resources.simpleserver"); }, access.findClassByName("sun.net.httpserver.simpleserver.SimpleFileServerImpl")); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java index 3c1c5e164616..a806ac544474 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java @@ -48,7 +48,7 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.ClassLoaderSupport.ConditionWithOrigin; @@ -305,7 +305,7 @@ public void registerNegativeQuery(Module module, String resourceName) { } @Platforms(Platform.HOSTED_ONLY.class) - public void registerIncludePattern(ConfigurationCondition condition, String module, String pattern) { + public void registerIncludePattern(InclusionCondition condition, String module, String pattern) { assert MissingRegistrationUtils.throwMissingRegistrationErrors(); synchronized (requestedPatterns) { updateTimeStamp(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java index 36d8bb4e6e21..4a5ad6bdd4ce 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java @@ -48,8 +48,8 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.RuntimeResourceSupport; @@ -181,7 +181,7 @@ public void registerRequiredReflectionAndResourcesForBundle(String baseName, Col if (i > 0) { String name = baseName.substring(i + 1) + "Provider"; String providerName = baseName.substring(0, i) + ".spi." + name; - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerClassLookup(ConfigurationCondition.alwaysTrue(), providerName); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerClassLookup(InclusionCondition.alwaysInclude(), providerName); } } @@ -282,7 +282,7 @@ private static void registerNullaryConstructor(Class bundleClass) { } @Platforms(Platform.HOSTED_ONLY.class) - public void registerBundleLookup(ConfigurationCondition condition, String baseName) { + public void registerBundleLookup(InclusionCondition condition, String baseName) { RuntimeConditionSet conditionSet = RuntimeConditionSet.emptySet(); var registered = registeredBundles.putIfAbsent(baseName, conditionSet); (registered == null ? conditionSet : registered).addCondition(condition); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/JNIRuntimeAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/JNIRuntimeAccess.java index 4e4080b7667e..e3ca9302bd40 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/JNIRuntimeAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/JNIRuntimeAccess.java @@ -30,8 +30,8 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeJNIAccess; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeJNIAccessSupport; /** @@ -56,6 +56,6 @@ public static void register(Field... fields) { } public static void register(boolean finalIsWritable, Field... fields) { - ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(ConfigurationCondition.alwaysTrue(), finalIsWritable, fields); + ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(InclusionCondition.alwaysInclude(), finalIsWritable, fields); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java index 75ff23639307..18dc5cf7e2d5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java @@ -32,9 +32,10 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeClassInitialization; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.impl.TypeCondition; import com.oracle.svm.core.configure.ConditionalRuntimeValue; import com.oracle.svm.core.configure.RuntimeConditionSet; @@ -101,8 +102,8 @@ public DynamicProxySupport() { @Override @Platforms(Platform.HOSTED_ONLY.class) - public synchronized void addProxyClass(ConfigurationCondition condition, Class... interfaces) { - VMError.guarantee(condition.isRuntimeChecked(), "The condition used must be a runtime condition."); + public synchronized void addProxyClass(InclusionCondition condition, Class... interfaces) { + VMError.guarantee(((TypeCondition) condition).isRuntimeChecked(), "The condition used must be a runtime condition."); /* * Make a defensive copy of the interfaces array to protect against the caller modifying the * array. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationSupport.java index d20b8382277a..a5c69dd17288 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationSupport.java @@ -38,7 +38,7 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import com.oracle.svm.core.configure.RuntimeConditionSet; import com.oracle.svm.core.reflect.SubstrateConstructorAccessor; @@ -191,7 +191,7 @@ public String getClassLoaderSerializationLookupKey(ClassLoader classLoader) { private final EconomicMap lambdaCapturingClasses = EconomicMap.create(); @Platforms(Platform.HOSTED_ONLY.class) - public void registerSerializationTargetClass(ConfigurationCondition cnd, Class serializationTargetClass) { + public void registerSerializationTargetClass(InclusionCondition cnd, Class serializationTargetClass) { synchronized (classes) { var previous = classes.putIfAbsent(serializationTargetClass, RuntimeConditionSet.createHosted(cnd)); if (previous != null) { @@ -201,7 +201,7 @@ public void registerSerializationTargetClass(ConfigurationCondition cnd, Class x instanceof DirectMethodHandleDesc dmh && dmh.kind() == Kind.STATIC) diff --git a/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/StronglyTypedRuntimeForeignAccessSupport.java b/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/StronglyTypedRuntimeForeignAccessSupport.java index 34f86a202923..48b491710ebe 100644 --- a/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/StronglyTypedRuntimeForeignAccessSupport.java +++ b/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/StronglyTypedRuntimeForeignAccessSupport.java @@ -28,7 +28,7 @@ import java.lang.foreign.Linker; import java.lang.invoke.MethodHandle; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.RuntimeForeignAccessSupport; /** @@ -55,50 +55,50 @@ private static Linker.Option[] castOptions(Object... optionsO) { @FunctionalInterface interface Recorder { - void apply(ConfigurationCondition condition, FunctionDescriptor desc, Linker.Option... options); + void apply(InclusionCondition condition, FunctionDescriptor desc, Linker.Option... options); } @FunctionalInterface interface DirectUpcallRecorder { - void apply(ConfigurationCondition condition, MethodHandle target, FunctionDescriptor desc, Linker.Option... options); + void apply(InclusionCondition condition, MethodHandle target, FunctionDescriptor desc, Linker.Option... options); } static StronglyTypedRuntimeForeignAccessSupport make(Recorder forDowncalls, Recorder forUpcalls, DirectUpcallRecorder forDirectUpcalls) { return new StronglyTypedRuntimeForeignAccessSupport() { @Override - public void registerForDowncall(ConfigurationCondition condition, FunctionDescriptor desc, Linker.Option... options) { + public void registerForDowncall(InclusionCondition condition, FunctionDescriptor desc, Linker.Option... options) { forDowncalls.apply(condition, desc, options); } @Override - public void registerForUpcall(ConfigurationCondition condition, FunctionDescriptor desc, Linker.Option... options) { + public void registerForUpcall(InclusionCondition condition, FunctionDescriptor desc, Linker.Option... options) { forUpcalls.apply(condition, desc, options); } @Override - public void registerForDirectUpcall(ConfigurationCondition condition, MethodHandle target, FunctionDescriptor fd, Linker.Option... options) { + public void registerForDirectUpcall(InclusionCondition condition, MethodHandle target, FunctionDescriptor fd, Linker.Option... options) { forDirectUpcalls.apply(condition, target, fd, options); } }; } @Override - default void registerForDowncall(ConfigurationCondition condition, Object descO, Object... optionsO) { + default void registerForDowncall(InclusionCondition condition, Object descO, Object... optionsO) { registerForDowncall(condition, castDesc(descO), castOptions(optionsO)); } - void registerForDowncall(ConfigurationCondition condition, FunctionDescriptor desc, Linker.Option... options); + void registerForDowncall(InclusionCondition condition, FunctionDescriptor desc, Linker.Option... options); @Override - default void registerForUpcall(ConfigurationCondition condition, Object descO, Object... optionsO) { + default void registerForUpcall(InclusionCondition condition, Object descO, Object... optionsO) { registerForUpcall(condition, castDesc(descO), castOptions(optionsO)); } - void registerForUpcall(ConfigurationCondition condition, FunctionDescriptor desc, Linker.Option... options); + void registerForUpcall(InclusionCondition condition, FunctionDescriptor desc, Linker.Option... options); - default void registerForDirectUpcall(ConfigurationCondition condition, MethodHandle target, Object desc, Object... options) { + default void registerForDirectUpcall(InclusionCondition condition, MethodHandle target, Object desc, Object... options) { registerForDirectUpcall(condition, target, castDesc(desc), castOptions(options)); } - void registerForDirectUpcall(ConfigurationCondition condition, MethodHandle target, FunctionDescriptor desc, Linker.Option... options); + void registerForDirectUpcall(InclusionCondition condition, MethodHandle target, FunctionDescriptor desc, Linker.Option... options); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderSupportImpl.java index c8dff0897002..4bb3889cb661 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderSupportImpl.java @@ -54,7 +54,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import com.oracle.svm.core.ClassLoaderSupport; import com.oracle.svm.core.util.ClasspathUtils; @@ -72,7 +72,7 @@ public class ClassLoaderSupportImpl extends ClassLoaderSupport { private final Map> packageToModules; - private record ConditionalResource(ConfigurationCondition condition, String resourceName, Object origin) { + private record ConditionalResource(InclusionCondition condition, String resourceName, Object origin) { } public ClassLoaderSupportImpl(NativeImageClassLoaderSupport classLoaderSupport) { @@ -220,13 +220,13 @@ private static void scanJar(Path jarPath, ResourceCollector collector, boolean i } } - private static void includeResource(ResourceCollector collector, Module module, String name, ConfigurationCondition condition, Object origin) { + private static void includeResource(ResourceCollector collector, Module module, String name, InclusionCondition condition, Object origin) { collector.addResourceConditionally(module, name, condition, origin); } private static List shouldIncludeEntry(Module module, ResourceCollector collector, String fileName, URI uri, boolean includeCurrent) { if (includeCurrent && !(fileName.endsWith(".class") || fileName.endsWith(".jar"))) { - return Collections.singletonList(new ConditionWithOrigin(ConfigurationCondition.alwaysTrue(), "Include all")); + return Collections.singletonList(new ConditionWithOrigin(InclusionCondition.alwaysInclude(), "Include all")); } return collector.isIncluded(module, fileName, uri); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ConditionalConfigurationRegistry.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ConditionalConfigurationRegistry.java index df72aa376f5d..b077195d07b1 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ConditionalConfigurationRegistry.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ConditionalConfigurationRegistry.java @@ -32,7 +32,8 @@ import java.util.function.Consumer; import org.graalvm.nativeimage.hosted.Feature; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; +import org.graalvm.nativeimage.impl.TypeCondition; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; @@ -41,36 +42,30 @@ public abstract class ConditionalConfigurationRegistry { private Feature.BeforeAnalysisAccess beforeAnalysisAccess; private final Map, Collection> pendingReachabilityHandlers = new ConcurrentHashMap<>(); - protected void registerConditionalConfiguration(ConfigurationCondition condition, Consumer consumer) { + protected void registerConditionalConfiguration(InclusionCondition condition, Consumer consumer) { Objects.requireNonNull(condition, "Cannot use null value as condition for conditional configuration. Please ensure that you register a non-null condition."); Objects.requireNonNull(consumer, "Cannot use null value as runnable for conditional configuration. Please ensure that you register a non-null runnable."); - if (condition.isRuntimeChecked() && !condition.isAlwaysTrue()) { + if (((TypeCondition) condition).isRuntimeChecked() && !((TypeCondition) condition).isAlwaysTrue()) { /* * We do this before the type is reached as the handler runs during analysis when it is * too late to register types for reached tracking. If the type is never reached, there * is no damage as subtypes will also never be reached. */ - ClassInitializationSupport.singleton().addForTypeReachedTracking(condition.getType()); + ClassInitializationSupport.singleton().addForTypeReachedTracking(((TypeCondition) condition).getKey()); } - if (ConfigurationCondition.alwaysTrue().equals(condition)) { + if (((TypeCondition) condition).isAlwaysTrue()) { /* analysis optimization to include new types as early as possible */ - consumer.accept(ConfigurationCondition.alwaysTrue()); + consumer.accept(InclusionCondition.alwaysInclude()); } else { - ConfigurationCondition runtimeCondition; - if (condition.isRuntimeChecked()) { - runtimeCondition = condition; - } else { - runtimeCondition = ConfigurationCondition.alwaysTrue(); - } + InclusionCondition runtimeCondition = ((TypeCondition) condition).isRuntimeChecked() ? condition : InclusionCondition.alwaysInclude(); + if (beforeAnalysisAccess == null) { - Collection handlers = pendingReachabilityHandlers.computeIfAbsent(condition.getType(), key -> new ConcurrentLinkedQueue<>()); + Collection handlers = pendingReachabilityHandlers.computeIfAbsent(((TypeCondition) condition).getKey(), key -> new ConcurrentLinkedQueue<>()); handlers.add(() -> consumer.accept(runtimeCondition)); } else { - beforeAnalysisAccess.registerReachabilityHandler(access -> consumer.accept(runtimeCondition), condition.getType()); + beforeAnalysisAccess.registerReachabilityHandler(access -> consumer.accept(runtimeCondition), ((TypeCondition) condition).getKey()); } - } - } public void setAnalysisAccess(Feature.BeforeAnalysisAccess beforeAnalysisAccess) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java index 8db5e3110ad2..9d4a088ab52f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java @@ -50,8 +50,10 @@ import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.Feature.DuringAnalysisAccess; import org.graalvm.nativeimage.hosted.FieldValueTransformer; +import org.graalvm.nativeimage.hosted.InclusionCondition; +import org.graalvm.nativeimage.hosted.ReflectionDynamicAccess; +import org.graalvm.nativeimage.hosted.ResourceDynamicAccess; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.ObjectScanner; @@ -192,6 +194,16 @@ public void setMainEntryPoint(Pair mainEntryPoint) { public Pair getMainEntryPoint() { return mainEntryPoint; } + + @Override + public ReflectionDynamicAccess createReflectionDynamicAccess() { + return new ReflectionDynamicAccessImpl(); + } + + @Override + public ResourceDynamicAccess createResourceDynamicAccess() { + return new ResourceDynamicAccessImpl(); + } } abstract static class AnalysisAccessBase extends FeatureAccessImpl { @@ -413,7 +425,7 @@ public void registerAsUnsafeAllocated(AnalysisType aType) { throw UserError.abort("Cannot register an abstract class as instantiated: " + aType.toJavaName(true)); } aType.registerAsUnsafeAllocated("From feature"); - classForNameSupport.registerUnsafeAllocated(ConfigurationCondition.alwaysTrue(), aType.getJavaClass()); + classForNameSupport.registerUnsafeAllocated(InclusionCondition.alwaysInclude(), aType.getJavaClass()); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/InternalReflectionDynamicAccessImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/InternalReflectionDynamicAccessImpl.java new file mode 100644 index 000000000000..bb277b21d142 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/InternalReflectionDynamicAccessImpl.java @@ -0,0 +1,65 @@ +package com.oracle.svm.hosted; + +import java.lang.reflect.Executable; +import java.lang.reflect.Field; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.InclusionCondition; +import org.graalvm.nativeimage.hosted.ReflectionDynamicAccess; +import org.graalvm.nativeimage.impl.RuntimeJNIAccessSupport; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; +import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; + +public class InternalReflectionDynamicAccessImpl implements ReflectionDynamicAccess { + + private static RuntimeReflectionSupport rrsInstance; + + InternalReflectionDynamicAccessImpl() { + rrsInstance = ImageSingletons.lookup(RuntimeReflectionSupport.class); + } + + @Override + public void register(InclusionCondition condition, Class... classes) { + rrsInstance.register(condition, classes); + for (Class clazz : classes) { + rrsInstance.registerAllClassesQuery(condition, clazz); + rrsInstance.registerAllDeclaredClassesQuery(condition, clazz); + rrsInstance.registerAllDeclaredMethodsQuery(condition, true, clazz); + rrsInstance.registerAllMethodsQuery(condition, true, clazz); + rrsInstance.registerAllDeclaredConstructorsQuery(condition, true, clazz); + rrsInstance.registerAllConstructorsQuery(condition, true, clazz); + rrsInstance.registerAllFieldsQuery(condition, true, clazz); + rrsInstance.registerAllDeclaredFieldsQuery(condition, true, clazz); + rrsInstance.registerAllNestMembersQuery(condition, clazz); + rrsInstance.registerAllPermittedSubclassesQuery(condition, clazz); + rrsInstance.registerAllRecordComponentsQuery(condition, clazz); + rrsInstance.registerAllSignersQuery(condition, clazz); + } + } + + @Override + public void registerClassLookup(InclusionCondition condition, String className) { + rrsInstance.registerClassLookup(condition, className); + } + + @Override + public void register(InclusionCondition condition, Executable... methods) { + rrsInstance.register(condition, false, methods); + } + + @Override + public void register(InclusionCondition condition, Field... fields) { + rrsInstance.register(condition, false, fields); + } + + @Override + public void registerForSerialization(InclusionCondition condition, Class... classes) { + register(condition, classes); + RuntimeSerializationSupport.singleton().register(condition, classes); + } + + @Override + public void registerForJNIAccess(InclusionCondition condition, Class... classes) { + ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(condition, classes); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/InternalResourceDynamicAccessImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/InternalResourceDynamicAccessImpl.java new file mode 100644 index 000000000000..ffdd53c55314 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/InternalResourceDynamicAccessImpl.java @@ -0,0 +1,37 @@ +package com.oracle.svm.hosted; + +import java.util.Objects; + +import org.graalvm.nativeimage.hosted.InclusionCondition; +import org.graalvm.nativeimage.hosted.ResourceDynamicAccess; +import org.graalvm.nativeimage.impl.RuntimeResourceSupport; + +public class InternalResourceDynamicAccessImpl implements ResourceDynamicAccess { + + private static RuntimeResourceSupport rrsInstance; + + InternalResourceDynamicAccessImpl() { + rrsInstance = RuntimeResourceSupport.singleton(); + } + + @Override + public void register(InclusionCondition condition, Module module, String pattern) { + if (pattern.replace("\\*", "").contains("*")) { + String moduleName = module == null ? null : module.getName(); + rrsInstance.addGlob(condition, moduleName, pattern, "Registered from API"); + } else { + rrsInstance.addResource(condition, module, pattern.replace("\\*", "*"), "Registered from API"); + } + } + + @Override + public void registerResourceBundle(InclusionCondition condition, Module module, String bundleName) { + rrsInstance.addResourceBundles(condition, withModuleName(module, bundleName)); + } + + private static String withModuleName(Module module, String str) { + Objects.requireNonNull(module); + Objects.requireNonNull(str); + return (module.isNamed() ? module.getName() : "ALL-UNNAMED") + ":" + str; + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 71e8b882582e..b9bb65f5fa64 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -71,10 +71,10 @@ import org.graalvm.nativeimage.c.struct.RawStructure; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.Feature.OnAnalysisExitAccess; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeReflection; import org.graalvm.nativeimage.impl.AnnotationExtractor; import org.graalvm.nativeimage.impl.CConstantValueSupport; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.SizeOfSupport; @@ -978,6 +978,8 @@ protected void setupNativeImage(String imageName, OptionValues options, Map feature.afterRegistration(access)); + ReflectionDynamicAccessImpl.setAfterRegistrationFinished(); + ResourceDynamicAccessImpl.setAfterRegistrationFinished(); setDefaultLibCIfMissing(); if (!Pair. empty().equals(access.getMainEntryPoint())) { setAndVerifyMainEntryPoint(access, entryPoints); @@ -1108,7 +1110,7 @@ protected void setupNativeImage(String imageName, OptionValues options, Map !(classesOrPackagesToIgnore.contains(c.getPackageName()) || classesOrPackagesToIgnore.contains(c.getName()))) - .forEach(c -> runtimeReflection.registerClassFully(ConfigurationCondition.alwaysTrue(), c)); + .forEach(c -> runtimeReflection.registerClassFully(InclusionCondition.alwaysInclude(), c)); for (String className : loader.classLoaderSupport.getClassNamesToPreserve()) { RuntimeReflection.registerClassLookup(className); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReflectionDynamicAccessImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReflectionDynamicAccessImpl.java new file mode 100644 index 000000000000..d30a0150c06a --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReflectionDynamicAccessImpl.java @@ -0,0 +1,73 @@ +package com.oracle.svm.hosted; + +import java.lang.reflect.Executable; +import java.lang.reflect.Field; +import java.util.Arrays; + +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.InclusionCondition; +import org.graalvm.nativeimage.hosted.ReflectionDynamicAccess; + +import com.oracle.svm.core.util.UserError; + +/** + * Instance of this class is used to register classes, methods, and fields for reflection, + * serialization and JNI access at runtime. It can only be created at + * {@link Feature#afterRegistration} via {@link Feature.AfterRegistrationAccess}. + */ +public final class ReflectionDynamicAccessImpl implements ReflectionDynamicAccess { + + private static boolean afterRegistrationFinished; + private static InternalReflectionDynamicAccessImpl rdaInstance; + + public ReflectionDynamicAccessImpl() { + rdaInstance = new InternalReflectionDynamicAccessImpl(); + afterRegistrationFinished = false; + } + + public static void setAfterRegistrationFinished() { + afterRegistrationFinished = true; + } + + @Override + public void register(InclusionCondition condition, Class... classes) { + UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register: %s", + Arrays.toString(classes)); + rdaInstance.register(condition, classes); + } + + @Override + public void registerClassLookup(InclusionCondition condition, String className) { + UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register: %s", + className); + rdaInstance.registerClassLookup(condition, className); + } + + @Override + public void register(InclusionCondition condition, Executable... methods) { + UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register: %s", + Arrays.toString(methods)); + rdaInstance.register(condition, methods); + } + + @Override + public void register(InclusionCondition condition, Field... fields) { + UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register: %s", + Arrays.toString(fields)); + rdaInstance.register(condition, fields); + } + + @Override + public void registerForSerialization(InclusionCondition condition, Class... classes) { + UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register: %s", + Arrays.toString(classes)); + rdaInstance.registerForSerialization(condition, classes); + } + + @Override + public void registerForJNIAccess(InclusionCondition condition, Class... classes) { + UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register: %s", + Arrays.toString(classes)); + rdaInstance.registerForJNIAccess(condition, classes); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourceDynamicAccessImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourceDynamicAccessImpl.java new file mode 100644 index 000000000000..c843be053006 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourceDynamicAccessImpl.java @@ -0,0 +1,41 @@ +package com.oracle.svm.hosted; + +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.InclusionCondition; +import org.graalvm.nativeimage.hosted.ResourceDynamicAccess; + +import com.oracle.svm.core.util.UserError; + +/** + * Instance of this class is used to Java resources and ResourceBundles that should be accessible at + * runtime. It can only be created at {@link Feature#afterRegistration} via + * {@link Feature.AfterRegistrationAccess}. + */ +public class ResourceDynamicAccessImpl implements ResourceDynamicAccess { + + private static boolean afterRegistrationFinished; + private static InternalResourceDynamicAccessImpl rdaInstance; + + ResourceDynamicAccessImpl() { + rdaInstance = new InternalResourceDynamicAccessImpl(); + afterRegistrationFinished = false; + } + + public static void setAfterRegistrationFinished() { + afterRegistrationFinished = true; + } + + @Override + public void register(InclusionCondition condition, Module module, String pattern) { + UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register glob: %s", pattern); + rdaInstance.register(condition, module, pattern); + } + + @Override + public void registerResourceBundle(InclusionCondition condition, Module module, String bundleName) { + UserError.guarantee(!afterRegistrationFinished, "There shouldn't be a registration for runtime access after afterRegistration period. You tried to register: %s", + bundleName); + rdaInstance.registerResourceBundle(condition, module, bundleName); + } + +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index 2f11afd2fc5e..19573df0ea64 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -56,9 +56,10 @@ import java.util.stream.Collectors; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeResourceAccess; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeResourceSupport; +import org.graalvm.nativeimage.impl.TypeCondition; import com.oracle.svm.configure.ConfigurationFile; import com.oracle.svm.configure.ResourceConfigurationParser; @@ -161,10 +162,10 @@ public static class Options { private boolean sealed = false; - private record ConditionalPattern(ConfigurationCondition condition, String pattern, Object origin) { + private record ConditionalPattern(InclusionCondition condition, String pattern, Object origin) { } - private record CompiledConditionalPattern(ConfigurationCondition condition, ResourcePattern compiledPattern, Object origin) { + private record CompiledConditionalPattern(InclusionCondition condition, ResourcePattern compiledPattern, Object origin) { } private Set resourcePatternWorkSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); @@ -174,7 +175,7 @@ private record CompiledConditionalPattern(ConfigurationCondition condition, Reso private int loadedConfigurations; private ImageClassLoader imageClassLoader; - private class ResourcesRegistryImpl extends ConditionalConfigurationRegistry implements ResourcesRegistry { + private class ResourcesRegistryImpl extends ConditionalConfigurationRegistry implements ResourcesRegistry { private final ClassInitializationSupport classInitializationSupport = ClassInitializationSupport.singleton(); private final Set alreadyAddedResources = new HashSet<>(); @@ -183,7 +184,7 @@ private class ResourcesRegistryImpl extends ConditionalConfigurationRegistry imp } @Override - public void addResources(ConfigurationCondition condition, String pattern, Object origin) { + public void addResources(InclusionCondition condition, String pattern, Object origin) { try { resourcePatternWorkSet.add(new ConditionalPattern(condition, pattern, origin)); } catch (UnsupportedOperationException e) { @@ -192,17 +193,17 @@ public void addResources(ConfigurationCondition condition, String pattern, Objec } @Override - public void addGlob(ConfigurationCondition condition, String module, String glob, Object origin) { + public void addGlob(InclusionCondition condition, String module, String glob, Object origin) { String canonicalGlob = NativeImageResourcePathRepresentation.toCanonicalForm(glob); String resolvedGlob = GlobUtils.transformToTriePath(canonicalGlob, module); globWorkSet.add(new ConditionalPattern(condition, resolvedGlob, origin)); } @Override - public void addCondition(ConfigurationCondition condition, Module module, String resourcePath) { + public void addCondition(InclusionCondition condition, Module module, String resourcePath) { var conditionalResource = Resources.currentLayer().getResource(createStorageKey(module, resourcePath)); if (conditionalResource != null) { - classInitializationSupport.addForTypeReachedTracking(condition.getType()); + classInitializationSupport.addForTypeReachedTracking(((TypeCondition) condition).getKey()); conditionalResource.getConditions().addCondition(condition); } } @@ -233,7 +234,7 @@ public void injectResource(Module module, String resourcePath, byte[] resourceCo } @Override - public void ignoreResources(ConfigurationCondition condition, String pattern) { + public void ignoreResources(InclusionCondition condition, String pattern) { registerConditionalConfiguration(condition, (cnd) -> { UserError.guarantee(!sealed, "Resources ignored too late: %s", pattern); @@ -242,17 +243,17 @@ public void ignoreResources(ConfigurationCondition condition, String pattern) { } @Override - public void addResourceBundles(ConfigurationCondition condition, String name) { + public void addResourceBundles(InclusionCondition condition, String name) { registerConditionalConfiguration(condition, (cnd) -> ImageSingletons.lookup(LocalizationFeature.class).prepareBundle(cnd, name)); } @Override - public void addClassBasedResourceBundle(ConfigurationCondition condition, String basename, String className) { + public void addClassBasedResourceBundle(InclusionCondition condition, String basename, String className) { registerConditionalConfiguration(condition, (cnd) -> ImageSingletons.lookup(LocalizationFeature.class).prepareClassResourceBundle(basename, className)); } @Override - public void addResourceBundles(ConfigurationCondition condition, String basename, Collection locales) { + public void addResourceBundles(InclusionCondition condition, String basename, Collection locales) { registerConditionalConfiguration(condition, (cnd) -> ImageSingletons.lookup(LocalizationFeature.class).prepareBundle(cnd, basename, locales)); } @@ -406,14 +407,14 @@ protected boolean collectEmbeddedResourcesInfo() { public void beforeAnalysis(BeforeAnalysisAccess a) { FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a; /* load and parse resource configuration files */ - ConfigurationConditionResolver conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(), + ConfigurationConditionResolver conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(), ClassInitializationSupport.singleton()); - ResourceConfigurationParser parser = ResourceConfigurationParser.create(true, conditionResolver, ResourcesRegistry.singleton(), + ResourceConfigurationParser parser = ResourceConfigurationParser.create(true, conditionResolver, ResourcesRegistry.singleton(), ConfigurationFiles.Options.getConfigurationParserOptions()); loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, imageClassLoader, "resource"); - ResourceConfigurationParser legacyParser = ResourceConfigurationParser.create(false, conditionResolver, ResourcesRegistry.singleton(), + ResourceConfigurationParser legacyParser = ResourceConfigurationParser.create(false, conditionResolver, ResourcesRegistry.singleton(), ConfigurationFiles.Options.getConfigurationParserOptions()); loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, imageClassLoader, "resource", ConfigurationFiles.Options.ResourceConfigurationFiles, ConfigurationFiles.Options.ResourceConfigurationResources, @@ -444,7 +445,7 @@ public void beforeAnalysis(BeforeAnalysisAccess a) { /* prepare regex patterns for resource registration */ resourcePatternWorkSet.addAll(Options.IncludeResources.getValue() .getValuesWithOrigins() - .map(e -> new ConditionalPattern(ConfigurationCondition.alwaysTrue(), e.value(), e.origin())) + .map(e -> new ConditionalPattern(InclusionCondition.alwaysInclude(), e.value(), e.origin())) .toList()); Set includePatterns = resourcePatternWorkSet .stream() @@ -583,7 +584,7 @@ public void addResourceEntry(Module module, String resourceName, Object origin) } @Override - public void addResourceConditionally(Module module, String resourceName, ConfigurationCondition condition, Object origin) { + public void addResourceConditionally(Module module, String resourceName, InclusionCondition condition, Object origin) { registerConditionalConfiguration(condition, cnd -> { addResourceEntry(module, resourceName, origin); ImageSingletons.lookup(RuntimeResourceSupport.class).addCondition(cnd, module, resourceName); @@ -601,7 +602,7 @@ public void registerNegativeQuery(Module module, String resourceName) { Resources.currentLayer().registerNegativeQuery(module, resourceName); } - public void registerIncludePattern(ConfigurationCondition condition, String module, String pattern) { + public void registerIncludePattern(InclusionCondition condition, String module, String pattern) { registerConditionalConfiguration(condition, cnd -> Resources.currentLayer().registerIncludePattern(cnd, module, pattern)); } } @@ -655,7 +656,7 @@ public void afterAnalysis(AfterAnalysisAccess access) { /* prepare resources GlobTrie for runtime */ GlobTrieNode root = Resources.currentLayer().getResourcesTrieRoot(); - CompressedGlobTrie.removeNodes(root, (conditionWithOrigin) -> !access.isReachable(conditionWithOrigin.condition().getType())); + CompressedGlobTrie.removeNodes(root, (conditionWithOrigin) -> !access.isReachable(((TypeCondition) conditionWithOrigin.condition()).getKey())); CompressedGlobTrie.finalize(root); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java index 0dfaeed8752c..c7f110dbced5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java @@ -37,12 +37,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; -import jdk.graal.compiler.hotspot.HotSpotBackendFactory; -import jdk.graal.compiler.hotspot.meta.DefaultHotSpotLoweringProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider; -import jdk.graal.compiler.truffle.hotspot.TruffleCallBoundaryInstrumentationFactory; -import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.hosted.RuntimeReflection; import org.graalvm.nativeimage.hosted.RuntimeResourceAccess; @@ -55,8 +49,14 @@ import com.oracle.svm.core.util.BasedOnJDKFile; import com.oracle.svm.hosted.analysis.Inflation; +import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; +import jdk.graal.compiler.hotspot.HotSpotBackendFactory; +import jdk.graal.compiler.hotspot.meta.DefaultHotSpotLoweringProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotInvocationPluginProvider; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionType; +import jdk.graal.compiler.truffle.hotspot.TruffleCallBoundaryInstrumentationFactory; +import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; import sun.util.locale.provider.LocaleDataMetaInfo; /** diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java index bd9801dfbba5..47294d20ddb0 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java @@ -41,7 +41,7 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.ReflectionRegistry; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; @@ -60,9 +60,9 @@ public final class ConfigurationParserUtils { - public static ReflectionConfigurationParser> create(String combinedFileKey, boolean combinedFileSchema, - ConfigurationConditionResolver conditionResolver, ReflectionRegistry registry, ProxyRegistry proxyRegistry, - RuntimeSerializationSupport serializationSupport, ImageClassLoader imageClassLoader) { + public static ReflectionConfigurationParser> create(String combinedFileKey, boolean combinedFileSchema, + ConfigurationConditionResolver conditionResolver, ReflectionRegistry registry, ProxyRegistry proxyRegistry, + RuntimeSerializationSupport serializationSupport, ImageClassLoader imageClassLoader) { return ReflectionConfigurationParser.create(combinedFileKey, combinedFileSchema, conditionResolver, RegistryAdapter.create(registry, proxyRegistry, serializationSupport, imageClassLoader), ConfigurationFiles.Options.getConfigurationParserOptions()); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ReflectionRegistryAdapter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ReflectionRegistryAdapter.java index f0679425fc82..3667d340df6a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ReflectionRegistryAdapter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ReflectionRegistryAdapter.java @@ -27,7 +27,7 @@ import java.lang.reflect.Proxy; import java.util.Arrays; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; @@ -41,9 +41,9 @@ public class ReflectionRegistryAdapter extends RegistryAdapter { private final RuntimeReflectionSupport reflectionSupport; private final ProxyRegistry proxyRegistry; - private final RuntimeSerializationSupport serializationSupport; + private final RuntimeSerializationSupport serializationSupport; - ReflectionRegistryAdapter(RuntimeReflectionSupport reflectionSupport, ProxyRegistry proxyRegistry, RuntimeSerializationSupport serializationSupport, + ReflectionRegistryAdapter(RuntimeReflectionSupport reflectionSupport, ProxyRegistry proxyRegistry, RuntimeSerializationSupport serializationSupport, ImageClassLoader classLoader) { super(reflectionSupport, classLoader); this.reflectionSupport = reflectionSupport; @@ -52,7 +52,7 @@ public class ReflectionRegistryAdapter extends RegistryAdapter { } @Override - public void registerType(ConfigurationCondition condition, Class type) { + public void registerType(InclusionCondition condition, Class type) { super.registerType(condition, type); if (Proxy.isProxyClass(type)) { proxyRegistry.accept(condition, Arrays.stream(type.getInterfaces()).map(Class::getTypeName).toList()); @@ -60,7 +60,7 @@ public void registerType(ConfigurationCondition condition, Class type) { } @Override - public TypeResult> resolveType(ConfigurationCondition condition, ConfigurationTypeDescriptor typeDescriptor, boolean allowPrimitives) { + public TypeResult> resolveType(InclusionCondition condition, ConfigurationTypeDescriptor typeDescriptor, boolean allowPrimitives) { TypeResult> result = super.resolveType(condition, typeDescriptor, allowPrimitives); if (!result.isPresent() && typeDescriptor instanceof NamedConfigurationTypeDescriptor namedDescriptor) { Throwable classLookupException = result.getException(); @@ -72,67 +72,67 @@ public TypeResult> resolveType(ConfigurationCondition condition, Config } @Override - public void registerPublicClasses(ConfigurationCondition condition, Class type) { + public void registerPublicClasses(InclusionCondition condition, Class type) { reflectionSupport.registerAllClassesQuery(condition, type); } @Override - public void registerDeclaredClasses(ConfigurationCondition condition, Class type) { + public void registerDeclaredClasses(InclusionCondition condition, Class type) { reflectionSupport.registerAllDeclaredClassesQuery(condition, type); } @Override - public void registerRecordComponents(ConfigurationCondition condition, Class type) { + public void registerRecordComponents(InclusionCondition condition, Class type) { reflectionSupport.registerAllRecordComponentsQuery(condition, type); } @Override - public void registerPermittedSubclasses(ConfigurationCondition condition, Class type) { + public void registerPermittedSubclasses(InclusionCondition condition, Class type) { reflectionSupport.registerAllPermittedSubclassesQuery(condition, type); } @Override - public void registerNestMembers(ConfigurationCondition condition, Class type) { + public void registerNestMembers(InclusionCondition condition, Class type) { reflectionSupport.registerAllNestMembersQuery(condition, type); } @Override - public void registerSigners(ConfigurationCondition condition, Class type) { + public void registerSigners(InclusionCondition condition, Class type) { reflectionSupport.registerAllSignersQuery(condition, type); } @Override - public void registerPublicFields(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerPublicFields(InclusionCondition condition, boolean queriedOnly, Class type) { ((ReflectionDataBuilder) reflectionSupport).registerAllFieldsQuery(condition, queriedOnly, type); } @Override - public void registerDeclaredFields(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerDeclaredFields(InclusionCondition condition, boolean queriedOnly, Class type) { ((ReflectionDataBuilder) reflectionSupport).registerAllDeclaredFieldsQuery(condition, queriedOnly, type); } @Override - public void registerPublicMethods(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerPublicMethods(InclusionCondition condition, boolean queriedOnly, Class type) { reflectionSupport.registerAllMethodsQuery(condition, queriedOnly, type); } @Override - public void registerDeclaredMethods(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerDeclaredMethods(InclusionCondition condition, boolean queriedOnly, Class type) { reflectionSupport.registerAllDeclaredMethodsQuery(condition, queriedOnly, type); } @Override - public void registerPublicConstructors(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerPublicConstructors(InclusionCondition condition, boolean queriedOnly, Class type) { reflectionSupport.registerAllConstructorsQuery(condition, queriedOnly, type); } @Override - public void registerDeclaredConstructors(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerDeclaredConstructors(InclusionCondition condition, boolean queriedOnly, Class type) { reflectionSupport.registerAllDeclaredConstructorsQuery(condition, queriedOnly, type); } @Override - public void registerAsSerializable(ConfigurationCondition condition, Class clazz) { + public void registerAsSerializable(InclusionCondition condition, Class clazz) { serializationSupport.register(condition, clazz); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/RegistryAdapter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/RegistryAdapter.java index abf03ac5e410..902ece88a001 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/RegistryAdapter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/RegistryAdapter.java @@ -33,7 +33,7 @@ import java.util.List; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.ReflectionRegistry; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; @@ -49,11 +49,11 @@ import com.oracle.svm.util.ClassUtil; import com.oracle.svm.util.TypeResult; -public class RegistryAdapter implements ReflectionConfigurationParserDelegate> { +public class RegistryAdapter implements ReflectionConfigurationParserDelegate> { private final ReflectionRegistry registry; private final ImageClassLoader classLoader; - public static RegistryAdapter create(ReflectionRegistry registry, ProxyRegistry proxyRegistry, RuntimeSerializationSupport serializationSupport, + public static RegistryAdapter create(ReflectionRegistry registry, ProxyRegistry proxyRegistry, RuntimeSerializationSupport serializationSupport, ImageClassLoader classLoader) { if (registry instanceof RuntimeReflectionSupport) { return new ReflectionRegistryAdapter((RuntimeReflectionSupport) registry, proxyRegistry, serializationSupport, classLoader); @@ -68,12 +68,12 @@ public static RegistryAdapter create(ReflectionRegistry registry, ProxyRegistry } @Override - public void registerType(ConfigurationCondition condition, Class type) { + public void registerType(InclusionCondition condition, Class type) { registry.register(condition, type); } @Override - public TypeResult> resolveType(ConfigurationCondition condition, ConfigurationTypeDescriptor typeDescriptor, boolean allowPrimitives) { + public TypeResult> resolveType(InclusionCondition condition, ConfigurationTypeDescriptor typeDescriptor, boolean allowPrimitives) { switch (typeDescriptor.getDescriptorType()) { case NAMED -> { NamedConfigurationTypeDescriptor namedDescriptor = (NamedConfigurationTypeDescriptor) typeDescriptor; @@ -133,67 +133,67 @@ private TypeResult> resolveProxyType(ProxyConfigurationTypeDescriptor t } @Override - public void registerPublicClasses(ConfigurationCondition condition, Class type) { + public void registerPublicClasses(InclusionCondition condition, Class type) { registry.register(condition, type.getClasses()); } @Override - public void registerDeclaredClasses(ConfigurationCondition condition, Class type) { + public void registerDeclaredClasses(InclusionCondition condition, Class type) { registry.register(condition, type.getDeclaredClasses()); } @Override - public void registerRecordComponents(ConfigurationCondition condition, Class type) { + public void registerRecordComponents(InclusionCondition condition, Class type) { } @Override - public void registerPermittedSubclasses(ConfigurationCondition condition, Class type) { + public void registerPermittedSubclasses(InclusionCondition condition, Class type) { } @Override - public void registerNestMembers(ConfigurationCondition condition, Class type) { + public void registerNestMembers(InclusionCondition condition, Class type) { } @Override - public void registerSigners(ConfigurationCondition condition, Class type) { + public void registerSigners(InclusionCondition condition, Class type) { } @Override - public void registerPublicFields(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerPublicFields(InclusionCondition condition, boolean queriedOnly, Class type) { if (!queriedOnly) { registry.register(condition, false, type.getFields()); } } @Override - public void registerDeclaredFields(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerDeclaredFields(InclusionCondition condition, boolean queriedOnly, Class type) { if (!queriedOnly) { registry.register(condition, false, type.getDeclaredFields()); } } @Override - public void registerPublicMethods(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerPublicMethods(InclusionCondition condition, boolean queriedOnly, Class type) { registry.register(condition, queriedOnly, type.getMethods()); } @Override - public void registerDeclaredMethods(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerDeclaredMethods(InclusionCondition condition, boolean queriedOnly, Class type) { registry.register(condition, queriedOnly, type.getDeclaredMethods()); } @Override - public void registerPublicConstructors(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerPublicConstructors(InclusionCondition condition, boolean queriedOnly, Class type) { registry.register(condition, queriedOnly, type.getConstructors()); } @Override - public void registerDeclaredConstructors(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public void registerDeclaredConstructors(InclusionCondition condition, boolean queriedOnly, Class type) { registry.register(condition, queriedOnly, type.getDeclaredConstructors()); } @Override - public void registerField(ConfigurationCondition condition, Class type, String fieldName, boolean allowWrite) throws NoSuchFieldException { + public void registerField(InclusionCondition condition, Class type, String fieldName, boolean allowWrite) throws NoSuchFieldException { try { registry.register(condition, allowWrite, type.getDeclaredField(fieldName)); } catch (NoSuchFieldException e) { @@ -206,7 +206,7 @@ public void registerField(ConfigurationCondition condition, Class type, Strin } @Override - public boolean registerAllMethodsWithName(ConfigurationCondition condition, boolean queriedOnly, Class type, String methodName) { + public boolean registerAllMethodsWithName(InclusionCondition condition, boolean queriedOnly, Class type, String methodName) { boolean found = false; Executable[] methods = type.getDeclaredMethods(); for (Executable method : methods) { @@ -219,14 +219,14 @@ public boolean registerAllMethodsWithName(ConfigurationCondition condition, bool } @Override - public boolean registerAllConstructors(ConfigurationCondition condition, boolean queriedOnly, Class type) { + public boolean registerAllConstructors(InclusionCondition condition, boolean queriedOnly, Class type) { Executable[] methods = type.getDeclaredConstructors(); registerExecutable(condition, queriedOnly, methods); return methods.length > 0; } @Override - public void registerUnsafeAllocated(ConfigurationCondition condition, Class clazz) { + public void registerUnsafeAllocated(InclusionCondition condition, Class clazz) { if (!clazz.isArray() && !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers())) { registry.register(condition, true, clazz); /* @@ -237,7 +237,7 @@ public void registerUnsafeAllocated(ConfigurationCondition condition, Class c } @Override - public void registerMethod(ConfigurationCondition condition, boolean queriedOnly, Class type, String methodName, List> methodParameterTypes) throws NoSuchMethodException { + public void registerMethod(InclusionCondition condition, boolean queriedOnly, Class type, String methodName, List> methodParameterTypes) throws NoSuchMethodException { try { Class[] parameterTypesArray = getParameterTypes(methodParameterTypes); Method method; @@ -270,7 +270,7 @@ public void registerMethod(ConfigurationCondition condition, boolean queriedOnly } @Override - public void registerConstructor(ConfigurationCondition condition, boolean queriedOnly, Class type, List> methodParameterTypes) throws NoSuchMethodException { + public void registerConstructor(InclusionCondition condition, boolean queriedOnly, Class type, List> methodParameterTypes) throws NoSuchMethodException { Class[] parameterTypesArray = getParameterTypes(methodParameterTypes); try { registerExecutable(condition, queriedOnly, type.getDeclaredConstructor(parameterTypesArray)); @@ -287,12 +287,12 @@ static Class[] getParameterTypes(List> methodParameterTypes) { return methodParameterTypes.toArray(Class[]::new); } - private void registerExecutable(ConfigurationCondition condition, boolean queriedOnly, Executable... executable) { + private void registerExecutable(InclusionCondition condition, boolean queriedOnly, Executable... executable) { registry.register(condition, queriedOnly, executable); } @Override - public void registerAsSerializable(ConfigurationCondition condition, Class clazz) { + public void registerAsSerializable(InclusionCondition condition, Class clazz) { /* Serializable has no effect on JNI registrations */ } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java index 53e199bf8281..d2aba359aded 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java @@ -29,6 +29,7 @@ import java.util.Arrays; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeReflection; import org.graalvm.nativeimage.hosted.RuntimeSerialization; @@ -38,7 +39,6 @@ import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; import com.oracle.svm.core.jni.JNIRuntimeAccess; import com.oracle.svm.util.ReflectionUtil; -import org.graalvm.nativeimage.impl.ConfigurationCondition; @AutomaticallyRegisteredFeature public class JmxCommonFeature implements InternalFeature { @@ -158,27 +158,27 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { */ private static void configureProxy(BeforeAnalysisAccess access) { DynamicProxyRegistry dynamicProxySupport = ImageSingletons.lookup(DynamicProxyRegistry.class); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("com.sun.management.GarbageCollectorMXBean"), + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("com.sun.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("com.sun.management.OperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("com.sun.management.ThreadMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("com.sun.management.UnixOperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.BufferPoolMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.ClassLoadingMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.CompilationMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.GarbageCollectorMXBean"), + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("com.sun.management.OperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("com.sun.management.ThreadMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("com.sun.management.UnixOperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.BufferPoolMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.ClassLoadingMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.CompilationMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.GarbageCollectorMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.MemoryManagerMXBean"), + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.MemoryManagerMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.MemoryManagerMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.MemoryPoolMXBean"), + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.MemoryManagerMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.MemoryPoolMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.MemoryMXBean"), + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.MemoryMXBean"), access.findClassByName("javax.management.NotificationEmitter")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.OperatingSystemMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.RuntimeMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.lang.management.ThreadMXBean")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("jdk.management.jfr.FlightRecorderMXBean"), + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.OperatingSystemMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.RuntimeMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.lang.management.ThreadMXBean")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("jdk.management.jfr.FlightRecorderMXBean"), access.findClassByName("javax.management.NotificationEmitter")); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java index 50367d43c976..9871307c4793 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java @@ -34,11 +34,11 @@ import javax.management.remote.JMXServiceURL; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.ConfigurationCondition; -import com.oracle.svm.core.VMInspectionOptions; import com.oracle.svm.configure.ResourcesRegistry; +import com.oracle.svm.core.VMInspectionOptions; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.jdk.NativeLibrarySupport; @@ -77,22 +77,22 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { } private static void registerJMXAgentResources() { - ResourcesRegistry resourcesRegistry = ResourcesRegistry.singleton(); + ResourcesRegistry resourcesRegistry = ResourcesRegistry.singleton(); - resourcesRegistry.addResourceBundles(ConfigurationCondition.alwaysTrue(), + resourcesRegistry.addResourceBundles(InclusionCondition.alwaysInclude(), "jdk.internal.agent.resources.agent"); - resourcesRegistry.addResourceBundles(ConfigurationCondition.alwaysTrue(), + resourcesRegistry.addResourceBundles(InclusionCondition.alwaysInclude(), "sun.security.util.Resources"); // required for password auth } private static void configureProxy(BeforeAnalysisAccess access) { DynamicProxyRegistry dynamicProxySupport = ImageSingletons.lookup(DynamicProxyRegistry.class); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("java.rmi.Remote"), + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("java.rmi.Remote"), access.findClassByName("java.rmi.registry.Registry")); - dynamicProxySupport.addProxyClass(ConfigurationCondition.alwaysTrue(), access.findClassByName("javax.management.remote.rmi.RMIServer")); + dynamicProxySupport.addProxyClass(InclusionCondition.alwaysInclude(), access.findClassByName("javax.management.remote.rmi.RMIServer")); } /** diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java index b9750af8e9bd..a5b32cffec82 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java @@ -63,7 +63,7 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import com.oracle.graal.pointsto.ObjectScanner; @@ -512,7 +512,7 @@ protected void addResourceBundles() { * Locale data bundle class names do not contain underscores */ String baseName = e.getClassName().split("_")[0]; - prepareNegativeBundle(ConfigurationCondition.alwaysTrue(), baseName, locale, true); + prepareNegativeBundle(InclusionCondition.alwaysInclude(), baseName, locale, true); continue; /* No bundle for this `locale`. */ } if (bundle instanceof ParallelListResourceBundle) { @@ -529,14 +529,14 @@ protected void addResourceBundles() { * No eager loading of bundle content, so we need to include the * `sun.text.resources.FormatData` bundle supplement as well. */ - prepareBundle(ConfigurationCondition.alwaysTrue(), "sun.text.resources.JavaTimeSupplementary"); + prepareBundle(InclusionCondition.alwaysInclude(), "sun.text.resources.JavaTimeSupplementary"); } final String[] alwaysRegisteredResourceBundles = new String[]{ "sun.util.logging.resources.logging" }; for (String bundleName : alwaysRegisteredResourceBundles) { - prepareBundle(ConfigurationCondition.alwaysTrue(), bundleName); + prepareBundle(InclusionCondition.alwaysInclude(), bundleName); } for (String bundleName : Options.IncludeResourceBundles.getValue().values()) { @@ -553,13 +553,13 @@ private void processRequestedBundle(String input) { if (locale != null) { /* Get rid of locale specific suffix. */ String baseName = input.substring(0, splitIndex); - prepareBundle(ConfigurationCondition.alwaysTrue(), baseName, Collections.singletonList(locale)); + prepareBundle(InclusionCondition.alwaysInclude(), baseName, Collections.singletonList(locale)); return; } else { trace("Cannot parse wanted locale " + input.substring(splitIndex + 1) + ", default will be used instead."); } } - prepareBundle(ConfigurationCondition.alwaysTrue(), input, allLocales); + prepareBundle(InclusionCondition.alwaysInclude(), input, allLocales); } @Platforms(Platform.HOSTED_ONLY.class) @@ -576,7 +576,7 @@ public void prepareClassResourceBundle(String basename, String className) { } @Platforms(Platform.HOSTED_ONLY.class) - public void prepareBundle(ConfigurationCondition condition, String baseName) { + public void prepareBundle(InclusionCondition condition, String baseName) { prepareBundle(condition, baseName, allLocales); } @@ -588,7 +588,7 @@ public void prepareBundle(ConfigurationCondition condition, String baseName) { }; @Platforms(Platform.HOSTED_ONLY.class) - public void prepareBundle(ConfigurationCondition condition, String baseName, Collection wantedLocales) { + public void prepareBundle(InclusionCondition condition, String baseName, Collection wantedLocales) { prepareBundleInternal(condition, baseName, wantedLocales); String alternativeBundleName = null; @@ -603,7 +603,7 @@ public void prepareBundle(ConfigurationCondition condition, String baseName, Col } } - private void prepareBundleInternal(ConfigurationCondition condition, String baseName, Collection wantedLocales) { + private void prepareBundleInternal(InclusionCondition condition, String baseName, Collection wantedLocales) { boolean somethingFound = false; for (Locale locale : wantedLocales) { support.registerBundleLookup(condition, baseName); @@ -660,7 +660,7 @@ private void prepareBundleInternal(ConfigurationCondition condition, String base } @Platforms(Platform.HOSTED_ONLY.class) - protected void prepareNegativeBundle(ConfigurationCondition condition, String baseName, Locale locale, boolean jdkBundle) { + protected void prepareNegativeBundle(InclusionCondition condition, String baseName, Locale locale, boolean jdkBundle) { support.registerBundleLookup(condition, baseName); support.registerRequiredReflectionAndResourcesForBundleAndLocale(baseName, locale, jdkBundle); } @@ -668,11 +668,11 @@ protected void prepareNegativeBundle(ConfigurationCondition condition, String ba @Platforms(Platform.HOSTED_ONLY.class) protected void prepareJDKBundle(ResourceBundle bundle, Locale locale) { String baseName = bundle.getBaseBundleName(); - prepareBundle(ConfigurationCondition.alwaysTrue(), baseName, bundle, locale, true); + prepareBundle(InclusionCondition.alwaysInclude(), baseName, bundle, locale, true); } @Platforms(Platform.HOSTED_ONLY.class) - private void prepareBundle(ConfigurationCondition condition, String bundleName, ResourceBundle bundle, Locale locale, boolean jdkBundle) { + private void prepareBundle(InclusionCondition condition, String bundleName, ResourceBundle bundle, Locale locale, boolean jdkBundle) { trace("Adding bundle " + bundleName + ", locale " + locale + " with condition " + condition); /* * Ensure that the bundle contents are loaded. We need to walk the whole bundle parent chain diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java index 6db907d0b1b6..736faae55632 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java @@ -50,8 +50,9 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.c.function.CodePointer; import org.graalvm.nativeimage.hosted.Feature; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.RuntimeJNIAccessSupport; +import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.word.PointerBase; import com.oracle.graal.pointsto.BigBang; @@ -69,6 +70,7 @@ import com.oracle.svm.core.config.ObjectLayout; import com.oracle.svm.core.configure.ConfigurationFiles; import com.oracle.svm.core.graal.meta.KnownOffsets; +import com.oracle.svm.core.hub.ClassForNameSupport; import com.oracle.svm.core.jni.CallVariant; import com.oracle.svm.core.jni.JNIJavaCallTrampolineHolder; import com.oracle.svm.core.jni.access.JNIAccessibleClass; @@ -103,6 +105,7 @@ import com.oracle.svm.hosted.meta.KnownOffsetsFeature; import com.oracle.svm.hosted.meta.MaterializedConstantFields; import com.oracle.svm.hosted.reflect.NativeImageConditionResolver; +import com.oracle.svm.hosted.reflect.ReflectionDataBuilder; import com.oracle.svm.hosted.reflect.proxy.DynamicProxyFeature; import com.oracle.svm.hosted.substitute.SubstitutionReflectivityFilter; import com.oracle.svm.util.ReflectionUtil; @@ -207,12 +210,12 @@ public void afterRegistration(AfterRegistrationAccess arg) { runtimeSupport = new JNIRuntimeAccessibilitySupportImpl(); ImageSingletons.add(RuntimeJNIAccessSupport.class, runtimeSupport); - ConfigurationConditionResolver conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(), + ConfigurationConditionResolver conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(), ClassInitializationSupport.singleton()); - ReflectionConfigurationParser> parser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, runtimeSupport, null, null, + ReflectionConfigurationParser> parser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, runtimeSupport, null, null, access.getImageClassLoader()); loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, access.getImageClassLoader(), "JNI"); - ReflectionConfigurationParser> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, runtimeSupport, null, null, + ReflectionConfigurationParser> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, runtimeSupport, null, null, access.getImageClassLoader()); loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "JNI", ConfigurationFiles.Options.JNIConfigurationFiles, ConfigurationFiles.Options.JNIConfigurationResources, ConfigurationFile.JNI.getFileName()); @@ -222,15 +225,38 @@ private final class JNIRuntimeAccessibilitySupportImpl extends ConditionalConfig implements RuntimeJNIAccessSupport { @Override - public void register(ConfigurationCondition condition, boolean unsafeAllocated, Class clazz) { + public void register(InclusionCondition condition, boolean unsafeAllocated, Class clazz) { assert !unsafeAllocated : "unsafeAllocated can be only set via Unsafe.allocateInstance, not via JNI."; Objects.requireNonNull(clazz, () -> nullErrorMessage("class")); abortIfSealed(); - registerConditionalConfiguration(condition, (cnd) -> newClasses.add(clazz)); + registerConditionalConfiguration(condition, (cnd) -> { + newClasses.add(clazz); + + /* + * If class is registered as JNI accessible, it should be registered for reflection + * at runtime as well. + */ + if (!ClassForNameSupport.currentLayer().getKnownClasses().contains(clazz.getName())) { + ImageSingletons.lookup(RuntimeReflectionSupport.class).register(InclusionCondition.alwaysInclude(), clazz); + } + /* + * All methods and fields that are registered for reflection, must be registered for + * JNI access if declaring type is JNI accessible + */ + Executable[] executables = ((ReflectionDataBuilder) ImageSingletons.lookup(RuntimeReflectionSupport.class)).getNotQueriedOnlyExecutables(clazz); + if (executables.length > 0) { + register(cnd, false, executables); + } + + Field[] fields = ((ReflectionDataBuilder) ImageSingletons.lookup(RuntimeReflectionSupport.class)).getReflectiveAccessibleFields(clazz); + if (fields.length > 0) { + register(cnd, false, fields); + } + }); } @Override - public void register(ConfigurationCondition condition, boolean queriedOnly, Executable... executables) { + public void register(InclusionCondition condition, boolean queriedOnly, Executable... executables) { requireNonNull(executables, "executable"); abortIfSealed(); if (!queriedOnly) { @@ -239,7 +265,7 @@ public void register(ConfigurationCondition condition, boolean queriedOnly, Exec } @Override - public void register(ConfigurationCondition condition, boolean finalIsWritable, Field... fields) { + public void register(InclusionCondition condition, boolean finalIsWritable, Field... fields) { requireNonNull(fields, "field"); abortIfSealed(); registerConditionalConfiguration(condition, (cnd) -> registerFields(finalIsWritable, fields)); @@ -253,7 +279,7 @@ private void registerFields(boolean finalIsWritable, Field[] fields) { } @Override - public void registerClassLookup(ConfigurationCondition condition, String typeName) { + public void registerClassLookup(InclusionCondition condition, String typeName) { try { register(condition, false, Class.forName(typeName)); } catch (ClassNotFoundException e) { @@ -262,7 +288,7 @@ public void registerClassLookup(ConfigurationCondition condition, String typeNam } @Override - public void registerFieldLookup(ConfigurationCondition condition, Class declaringClass, String fieldName) { + public void registerFieldLookup(InclusionCondition condition, Class declaringClass, String fieldName) { try { register(condition, false, declaringClass.getDeclaredField(fieldName)); } catch (NoSuchFieldException e) { @@ -271,7 +297,7 @@ public void registerFieldLookup(ConfigurationCondition condition, Class decla } @Override - public void registerMethodLookup(ConfigurationCondition condition, Class declaringClass, String methodName, Class... parameterTypes) { + public void registerMethodLookup(InclusionCondition condition, Class declaringClass, String methodName, Class... parameterTypes) { try { register(condition, false, declaringClass.getDeclaredMethod(methodName, parameterTypes)); } catch (NoSuchMethodException e) { @@ -280,7 +306,7 @@ public void registerMethodLookup(ConfigurationCondition condition, Class decl } @Override - public void registerConstructorLookup(ConfigurationCondition condition, Class declaringClass, Class... parameterTypes) { + public void registerConstructorLookup(InclusionCondition condition, Class declaringClass, Class... parameterTypes) { try { register(condition, false, declaringClass.getDeclaredConstructor(parameterTypes)); } catch (NoSuchMethodException e) { @@ -525,6 +551,18 @@ private static void addNegativeFieldLookup(Class declaringClass, String field jniClass.addFieldIfAbsent(fieldName, d -> JNIAccessibleField.negativeFieldQuery(jniClass)); } + public Set> getJNIAccessibleTypes() { + return newClasses; + } + + public Set getJNIAccessibleMethods() { + return newMethods; + } + + public Set getJNIAccessibleFields() { + return newFields.keySet(); + } + @Override @SuppressWarnings("unused") public void afterAnalysis(AfterAnalysisAccess access) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/NativeImageConditionResolver.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/NativeImageConditionResolver.java index 2912bd94558c..09eb6dc9991f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/NativeImageConditionResolver.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/NativeImageConditionResolver.java @@ -24,7 +24,8 @@ */ package com.oracle.svm.hosted.reflect; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; +import org.graalvm.nativeimage.impl.TypeCondition; import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition; import com.oracle.svm.configure.ConfigurationTypeDescriptor; @@ -33,7 +34,7 @@ import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.util.TypeResult; -public class NativeImageConditionResolver implements ConfigurationConditionResolver { +public class NativeImageConditionResolver implements ConfigurationConditionResolver { private final ImageClassLoader classLoader; @SuppressWarnings({"FieldCanBeLocal", "unused"}) private final ClassInitializationSupport classInitializationSupport; @@ -43,7 +44,7 @@ public NativeImageConditionResolver(ImageClassLoader classLoader, ClassInitializ } @Override - public TypeResult resolveCondition(UnresolvedConfigurationCondition unresolvedCondition) { + public TypeResult resolveCondition(UnresolvedConfigurationCondition unresolvedCondition) { String canonicalizedName = ConfigurationTypeDescriptor.canonicalizeTypeName(unresolvedCondition.getTypeName()); TypeResult> clazz = classLoader.findClass(canonicalizedName); return clazz.map(type -> { @@ -52,12 +53,12 @@ public TypeResult resolveCondition(UnresolvedConfigurati * reachability checks. */ var runtimeChecked = !classInitializationSupport.isAlwaysReached(type) && unresolvedCondition.isRuntimeChecked(); - return ConfigurationCondition.create(type, runtimeChecked); + return TypeCondition.create(type, runtimeChecked); }); } @Override - public ConfigurationCondition alwaysTrue() { - return ConfigurationCondition.alwaysTrue(); + public InclusionCondition alwaysTrue() { + return InclusionCondition.alwaysInclude(); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java index 204208ab871c..29ce1fd42d11 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java @@ -37,7 +37,6 @@ import static com.oracle.svm.core.code.RuntimeMetadataDecoderImpl.ALL_PERMITTED_SUBCLASSES_FLAG; import static com.oracle.svm.core.code.RuntimeMetadataDecoderImpl.ALL_RECORD_COMPONENTS_FLAG; import static com.oracle.svm.core.code.RuntimeMetadataDecoderImpl.ALL_SIGNERS_FLAG; -import static com.oracle.svm.core.configure.ConfigurationFiles.Options.TreatAllTypeReachableConditionsAsTypeReached; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Executable; @@ -68,9 +67,10 @@ import java.util.stream.Collectors; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeProxyCreation; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.impl.RuntimeJNIAccessSupport; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import com.oracle.graal.pointsto.ObjectScanner.ScanReason; @@ -95,6 +95,7 @@ import com.oracle.svm.hosted.annotation.AnnotationValue; import com.oracle.svm.hosted.annotation.SubstrateAnnotationExtractor; import com.oracle.svm.hosted.annotation.TypeAnnotationValue; +import com.oracle.svm.hosted.jni.JNIAccessFeature; import com.oracle.svm.hosted.substitute.SubstitutionReflectivityFilter; import com.oracle.svm.util.LogUtils; import com.oracle.svm.util.ReflectionUtil; @@ -122,6 +123,7 @@ public class ReflectionDataBuilder extends ConditionalConfigurationRegistry impl private final Map, Set>> innerClasses = new ConcurrentHashMap<>(); private final Map, Integer> enabledQueriesFlags = new ConcurrentHashMap<>(); private final Map>> registeredFields = new ConcurrentHashMap<>(); + private final Set reflectiveAccessibleFields = new HashSet<>(); private final Set hidingFields = ConcurrentHashMap.newKeySet(); private final Map>> registeredMethods = new ConcurrentHashMap<>(); private final Map methodAccessors = new ConcurrentHashMap<>(); @@ -148,7 +150,7 @@ public class ReflectionDataBuilder extends ConditionalConfigurationRegistry impl private final Map> processedTypes = new ConcurrentHashMap<>(); private final Map, Set> pendingRecordClasses; - record ConditionalTask(ConfigurationCondition condition, Consumer task) { + record ConditionalTask(InclusionCondition condition, Consumer task) { } private final Set pendingConditionalTasks = ConcurrentHashMap.newKeySet(); @@ -158,7 +160,7 @@ record ConditionalTask(ConfigurationCondition condition, Consumer filteredParameterAnnotations = new ConcurrentHashMap<>(); private final Map filteredTypeAnnotations = new ConcurrentHashMap<>(); - ReflectionDataBuilder(SubstrateAnnotationExtractor annotationExtractor) { + public ReflectionDataBuilder(SubstrateAnnotationExtractor annotationExtractor) { this.annotationExtractor = annotationExtractor; pendingRecordClasses = !throwMissingRegistrationErrors() ? new ConcurrentHashMap<>() : null; classForNameSupport = ClassForNameSupport.currentLayer(); @@ -177,9 +179,9 @@ public void beforeAnalysis(BeforeAnalysisAccessImpl beforeAnalysisAccess) { this.analysisAccess = beforeAnalysisAccess; } - private void runConditionalInAnalysisTask(ConfigurationCondition condition, Consumer task) { + private void runConditionalInAnalysisTask(InclusionCondition condition, Consumer task) { if (sealed) { - throw new UnsupportedFeatureException("Too late to add classes, methods, and fields for reflective access. Registration must happen in a Feature before the analysis has finished."); + throw new UnsupportedFeatureException("Too late to add classes, methods, and fields for reflective access. Registration must happen before the analysis has finished."); } if (universe != null) { @@ -199,14 +201,13 @@ private boolean isQueryFlagSet(Class clazz, int flag) { } @Override - public void register(ConfigurationCondition condition, boolean unsafeInstantiated, Class clazz) { + public void register(InclusionCondition condition, boolean unsafeInstantiated, Class clazz) { Objects.requireNonNull(clazz, () -> nullErrorMessage("class")); runConditionalInAnalysisTask(condition, (cnd) -> registerClass(cnd, clazz, unsafeInstantiated, true)); } @Override - public void registerAllClassesQuery(ConfigurationCondition condition, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, true); + public void registerAllClassesQuery(InclusionCondition condition, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_CLASSES_FLAG); try { @@ -223,19 +224,8 @@ public void registerAllClassesQuery(ConfigurationCondition condition, Class c }); } - /** - * Runtime conditions can only be used with type, so they are not valid here. - */ - @SuppressWarnings("unused") - private static void guaranteeNotRuntimeConditionForQueries(ConfigurationCondition cnd, boolean queriedOnly) { - if (!TreatAllTypeReachableConditionsAsTypeReached.getValue()) { - VMError.guarantee(!queriedOnly || cnd.isAlwaysTrue() || !cnd.isRuntimeChecked(), "Bulk queries can only be set with 'name' which does not allow run-time conditions."); - } - } - @Override - public void registerAllDeclaredClassesQuery(ConfigurationCondition condition, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, true); + public void registerAllDeclaredClassesQuery(InclusionCondition condition, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_DECLARED_CLASSES_FLAG); try { @@ -249,7 +239,7 @@ public void registerAllDeclaredClassesQuery(ConfigurationCondition condition, Cl }); } - private void registerClass(ConfigurationCondition condition, Class clazz, boolean unsafeInstantiated, boolean allowForName) { + private void registerClass(InclusionCondition condition, Class clazz, boolean unsafeInstantiated, boolean allowForName) { if (shouldExcludeClass(clazz)) { return; } @@ -285,12 +275,12 @@ private void registerClass(ConfigurationCondition condition, Class clazz, boo } @Override - public void registerClassLookupException(ConfigurationCondition condition, String typeName, Throwable t) { + public void registerClassLookupException(InclusionCondition condition, String typeName, Throwable t) { runConditionalInAnalysisTask(condition, (cnd) -> classForNameSupport.registerExceptionForClass(cnd, typeName, t)); } @Override - public void registerClassLookup(ConfigurationCondition condition, String typeName) { + public void registerClassLookup(InclusionCondition condition, String typeName) { runConditionalInAnalysisTask(condition, (cnd) -> { try { registerClass(cnd, Class.forName(typeName, false, ClassLoader.getSystemClassLoader()), false, true); @@ -303,8 +293,7 @@ public void registerClassLookup(ConfigurationCondition condition, String typeNam } @Override - public void registerAllRecordComponentsQuery(ConfigurationCondition condition, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, true); + public void registerAllRecordComponentsQuery(InclusionCondition condition, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_RECORD_COMPONENTS_FLAG); registerRecordComponents(clazz); @@ -312,8 +301,7 @@ public void registerAllRecordComponentsQuery(ConfigurationCondition condition, C } @Override - public void registerAllPermittedSubclassesQuery(ConfigurationCondition condition, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, true); + public void registerAllPermittedSubclassesQuery(InclusionCondition condition, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_PERMITTED_SUBCLASSES_FLAG); if (clazz.isSealed()) { @@ -325,8 +313,7 @@ public void registerAllPermittedSubclassesQuery(ConfigurationCondition condition } @Override - public void registerAllNestMembersQuery(ConfigurationCondition condition, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, true); + public void registerAllNestMembersQuery(InclusionCondition condition, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_NEST_MEMBERS_FLAG); for (Class nestMember : clazz.getNestMembers()) { @@ -338,8 +325,7 @@ public void registerAllNestMembersQuery(ConfigurationCondition condition, Class< } @Override - public void registerAllSignersQuery(ConfigurationCondition condition, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, true); + public void registerAllSignersQuery(InclusionCondition condition, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_SIGNERS_FLAG); Object[] signers = clazz.getSigners(); @@ -352,14 +338,13 @@ public void registerAllSignersQuery(ConfigurationCondition condition, Class c } @Override - public void register(ConfigurationCondition condition, boolean queriedOnly, Executable... executables) { + public void register(InclusionCondition condition, boolean queriedOnly, Executable... executables) { requireNonNull(executables, "executable"); runConditionalInAnalysisTask(condition, (cnd) -> registerMethods(cnd, queriedOnly, executables)); } @Override - public void registerAllMethodsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, queriedOnly); + public void registerAllMethodsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { for (Class current = clazz; current != null; current = current.getSuperclass()) { setQueryFlag(current, ALL_METHODS_FLAG); @@ -373,8 +358,7 @@ public void registerAllMethodsQuery(ConfigurationCondition condition, boolean qu } @Override - public void registerAllDeclaredMethodsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, queriedOnly); + public void registerAllDeclaredMethodsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_DECLARED_METHODS_FLAG); try { @@ -386,8 +370,7 @@ public void registerAllDeclaredMethodsQuery(ConfigurationCondition condition, bo } @Override - public void registerAllConstructorsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, queriedOnly); + public void registerAllConstructorsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { for (Class current = clazz; current != null; current = current.getSuperclass()) { setQueryFlag(current, ALL_CONSTRUCTORS_FLAG); @@ -401,8 +384,7 @@ public void registerAllConstructorsQuery(ConfigurationCondition condition, boole } @Override - public void registerAllDeclaredConstructorsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, queriedOnly); + public void registerAllDeclaredConstructorsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_DECLARED_CONSTRUCTORS_FLAG); try { @@ -413,13 +395,13 @@ public void registerAllDeclaredConstructorsQuery(ConfigurationCondition conditio }); } - private void registerMethods(ConfigurationCondition cnd, boolean queriedOnly, Executable[] reflectExecutables) { + private void registerMethods(InclusionCondition cnd, boolean queriedOnly, Executable[] reflectExecutables) { for (Executable reflectExecutable : reflectExecutables) { registerMethod(cnd, queriedOnly, reflectExecutable); } } - private void registerMethod(ConfigurationCondition cnd, boolean queriedOnly, Executable reflectExecutable) { + private void registerMethod(InclusionCondition cnd, boolean queriedOnly, Executable reflectExecutable) { if (SubstitutionReflectivityFilter.shouldExclude(reflectExecutable, metaAccess, universe)) { return; } @@ -492,11 +474,17 @@ private void registerMethod(ConfigurationCondition cnd, boolean queriedOnly, Exe return accessor; }); } + + /* Ensure that any method not registered as queriedOnly is registered as JNI-accessible */ + Set JNIAccessibleMethods = JNIAccessFeature.singleton().getJNIAccessibleMethods(); + Set> JNIAccessibleClasses = JNIAccessFeature.singleton().getJNIAccessibleTypes(); + if (!JNIAccessibleMethods.contains(reflectExecutable) && JNIAccessibleClasses.contains(declaringType.getJavaClass()) && !queriedOnly) { + ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(cnd, false, reflectExecutable); + } } @Override - public void registerMethodLookup(ConfigurationCondition condition, Class declaringClass, String methodName, Class... parameterTypes) { - guaranteeNotRuntimeConditionForQueries(condition, true); + public void registerMethodLookup(InclusionCondition condition, Class declaringClass, String methodName, Class... parameterTypes) { runConditionalInAnalysisTask(condition, (cnd) -> { try { registerMethod(cnd, true, declaringClass.getDeclaredMethod(methodName, parameterTypes)); @@ -510,8 +498,7 @@ public void registerMethodLookup(ConfigurationCondition condition, Class decl } @Override - public void registerConstructorLookup(ConfigurationCondition condition, Class declaringClass, Class... parameterTypes) { - guaranteeNotRuntimeConditionForQueries(condition, true); + public void registerConstructorLookup(InclusionCondition condition, Class declaringClass, Class... parameterTypes) { runConditionalInAnalysisTask(condition, (cnd) -> { try { registerMethod(cnd, true, declaringClass.getDeclaredConstructor(parameterTypes)); @@ -525,18 +512,18 @@ public void registerConstructorLookup(ConfigurationCondition condition, Class } @Override - public void register(ConfigurationCondition condition, boolean finalIsWritable, Field... fields) { + public void register(InclusionCondition condition, boolean finalIsWritable, Field... fields) { requireNonNull(fields, "field"); runConditionalInAnalysisTask(condition, (cnd) -> registerFields(cnd, false, fields)); } @Override - public void registerAllFields(ConfigurationCondition condition, Class clazz) { + public void registerAllFields(InclusionCondition condition, Class clazz) { registerAllFieldsQuery(condition, false, clazz); } - public void registerAllFieldsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz) { - guaranteeNotRuntimeConditionForQueries(condition, queriedOnly); + @Override + public void registerAllFieldsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { for (Class current = clazz; current != null; current = current.getSuperclass()) { setQueryFlag(current, ALL_FIELDS_FLAG); @@ -550,11 +537,12 @@ public void registerAllFieldsQuery(ConfigurationCondition condition, boolean que } @Override - public void registerAllDeclaredFields(ConfigurationCondition condition, Class clazz) { + public void registerAllDeclaredFields(InclusionCondition condition, Class clazz) { registerAllDeclaredFieldsQuery(condition, false, clazz); } - public void registerAllDeclaredFieldsQuery(ConfigurationCondition condition, boolean queriedOnly, Class clazz) { + @Override + public void registerAllDeclaredFieldsQuery(InclusionCondition condition, boolean queriedOnly, Class clazz) { runConditionalInAnalysisTask(condition, (cnd) -> { setQueryFlag(clazz, ALL_DECLARED_FIELDS_FLAG); try { @@ -565,13 +553,13 @@ public void registerAllDeclaredFieldsQuery(ConfigurationCondition condition, boo }); } - private void registerFields(ConfigurationCondition cnd, boolean queriedOnly, Field[] reflectFields) { + private void registerFields(InclusionCondition cnd, boolean queriedOnly, Field[] reflectFields) { for (Field reflectField : reflectFields) { registerField(cnd, queriedOnly, reflectField); } } - private void registerField(ConfigurationCondition cnd, boolean queriedOnly, Field reflectField) { + private void registerField(InclusionCondition cnd, boolean queriedOnly, Field reflectField) { if (SubstitutionReflectivityFilter.shouldExclude(reflectField, metaAccess, universe)) { return; } @@ -619,11 +607,19 @@ private void registerField(ConfigurationCondition cnd, boolean queriedOnly, Fiel /* queryOnly methods are conditioned on the type itself */ cndValue.getConditions().addCondition(cnd); registerTypesForField(analysisField, reflectField, false); + reflectiveAccessibleFields.add(reflectField); + } + + /* Ensure that any field not registered as queriedOnly is registered as JNI-accessible */ + Set JNIAccessibleFields = JNIAccessFeature.singleton().getJNIAccessibleFields(); + Set> JNIAccessibleClasses = JNIAccessFeature.singleton().getJNIAccessibleTypes(); + if (!JNIAccessibleFields.contains(reflectField) && JNIAccessibleClasses.contains(declaringClass.getJavaClass()) && !queriedOnly) { + ImageSingletons.lookup(RuntimeJNIAccessSupport.class).register(cnd, false, reflectField); } } @Override - public void registerFieldLookup(ConfigurationCondition condition, Class declaringClass, String fieldName) { + public void registerFieldLookup(InclusionCondition condition, Class declaringClass, String fieldName) { runConditionalInAnalysisTask(condition, (cnd) -> { try { registerField(cnd, false, declaringClass.getDeclaredField(fieldName)); @@ -648,8 +644,7 @@ private void processAnnotationMethod(boolean queriedOnly, Method method) { Class annotationClass = method.getDeclaringClass(); Class proxyClass = Proxy.getProxyClass(annotationClass.getClassLoader(), annotationClass); try { - /* build-time condition as it is registered during analysis */ - var condition = ConfigurationCondition.create(proxyClass, false); + var condition = InclusionCondition.alwaysInclude(); register(condition, queriedOnly, proxyClass.getDeclaredMethod(method.getName(), method.getParameterTypes())); } catch (NoSuchMethodException e) { /* @@ -659,7 +654,7 @@ private void processAnnotationMethod(boolean queriedOnly, Method method) { } @SuppressWarnings("deprecation") - private void processAnnotationField(ConfigurationCondition cnd, Field field) { + private void processAnnotationField(InclusionCondition cnd, Field field) { Class annotationClass = field.getDeclaringClass(); Class proxyClass = Proxy.getProxyClass(annotationClass.getClassLoader(), annotationClass); try { @@ -949,7 +944,7 @@ private void registerTypesForGenericSignature(Type type, int dimension) { private void registerTypesForRecordComponent(RecordComponent recordComponent) { Method accessorOrNull = recordComponent.getAccessor(); if (accessorOrNull != null) { - register(ConfigurationCondition.alwaysTrue(), true, accessorOrNull); + register(InclusionCondition.alwaysInclude(), true, accessorOrNull); } registerTypesForAnnotations(recordComponent); registerTypesForTypeAnnotations(recordComponent); @@ -1176,6 +1171,15 @@ public Object getAccessor(AnalysisMethod method) { return methodAccessors.get(method); } + public Executable[] getNotQueriedOnlyExecutables(Class declaringType) { + return methodAccessors.keySet().stream().filter(analysisMethod -> analysisMethod.getDeclaringClass().getJavaClass().equals(declaringType)).map(AnalysisMethod::getJavaMethod) + .collect(Collectors.toSet()).toArray(new Executable[0]); + } + + public Field[] getReflectiveAccessibleFields(Class declaringType) { + return reflectiveAccessibleFields.stream().filter(field -> field.getDeclaringClass().equals(declaringType)).collect(Collectors.toSet()).toArray(new Field[0]); + } + @Override public Set getHidingReflectionFields() { assert sealed; @@ -1224,7 +1228,7 @@ public void registerHeapReflectionField(Field reflectField, ScanReason reason) { if (!SubstitutionReflectivityFilter.shouldExclude(reflectField, metaAccess, universe)) { registerTypesForField(analysisField, reflectField, false); if (analysisField.getDeclaringClass().isAnnotation()) { - processAnnotationField(ConfigurationCondition.alwaysTrue(), reflectField); + processAnnotationField(InclusionCondition.alwaysInclude(), reflectField); } } } @@ -1351,7 +1355,7 @@ private static String nullErrorMessage(String kind) { public static class TestBackdoor { public static void registerField(ReflectionDataBuilder reflectionDataBuilder, boolean queriedOnly, Field field) { - reflectionDataBuilder.runConditionalInAnalysisTask(ConfigurationCondition.alwaysTrue(), (cnd) -> reflectionDataBuilder.registerField(cnd, queriedOnly, field)); + reflectionDataBuilder.runConditionalInAnalysisTask(InclusionCondition.alwaysInclude(), (cnd) -> reflectionDataBuilder.registerField(cnd, queriedOnly, field)); } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java index 0c2ef3583140..78272c719681 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java @@ -42,9 +42,9 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.c.function.CFunctionPointer; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeReflection; import org.graalvm.nativeimage.impl.AnnotationExtractor; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; @@ -52,13 +52,13 @@ import com.oracle.graal.pointsto.infrastructure.UniverseMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.svm.configure.ConfigurationFile; +import com.oracle.svm.configure.ReflectionConfigurationParser; import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.annotate.Delete; -import com.oracle.svm.configure.ConfigurationFile; import com.oracle.svm.core.configure.ConfigurationFiles; -import com.oracle.svm.configure.ReflectionConfigurationParser; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.fieldvaluetransformer.FieldValueTransformerWithAvailability; @@ -295,11 +295,11 @@ public void duringSetup(DuringSetupAccess a) { var conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(), ClassInitializationSupport.singleton()); reflectionData.duringSetup(access.getMetaAccess(), aUniverse); ProxyRegistry proxyRegistry = ImageSingletons.lookup(ProxyRegistry.class); - RuntimeSerializationSupport serializationSupport = RuntimeSerializationSupport.singleton(); - ReflectionConfigurationParser> parser = ConfigurationParserUtils.create(REFLECTION_KEY, true, conditionResolver, reflectionData, proxyRegistry, + RuntimeSerializationSupport serializationSupport = RuntimeSerializationSupport.singleton(); + ReflectionConfigurationParser> parser = ConfigurationParserUtils.create(REFLECTION_KEY, true, conditionResolver, reflectionData, proxyRegistry, serializationSupport, access.getImageClassLoader()); loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, access.getImageClassLoader(), "reflection"); - ReflectionConfigurationParser> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, reflectionData, proxyRegistry, + ReflectionConfigurationParser> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, reflectionData, proxyRegistry, serializationSupport, access.getImageClassLoader()); loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "reflection", ConfigurationFiles.Options.ReflectionConfigurationFiles, ConfigurationFiles.Options.ReflectionConfigurationResources, @@ -310,7 +310,7 @@ public void duringSetup(DuringSetupAccess a) { /* Primitive classes cannot be accessed through Class.forName() */ for (Class primitiveClass : PRIMITIVE_CLASSES) { - ClassForNameSupport.currentLayer().registerNegativeQuery(ConfigurationCondition.alwaysTrue(), primitiveClass.getName()); + ClassForNameSupport.currentLayer().registerNegativeQuery(InclusionCondition.alwaysInclude(), primitiveClass.getName()); } access.registerObjectReachableCallback(SubstrateAccessor.class, ReflectionFeature::onAccessorReachable); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/proxy/DynamicProxyFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/proxy/DynamicProxyFeature.java index 4231340be5a4..b338a9474955 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/proxy/DynamicProxyFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/proxy/DynamicProxyFeature.java @@ -25,7 +25,7 @@ package com.oracle.svm.hosted.reflect.proxy; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.impl.RuntimeProxyCreationSupport; import com.oracle.svm.configure.ConfigurationFile; @@ -68,9 +68,9 @@ public void afterRegistration(AfterRegistrationAccess a) { public void duringSetup(DuringSetupAccess a) { DuringSetupAccessImpl access = (DuringSetupAccessImpl) a; ImageClassLoader imageClassLoader = access.getImageClassLoader(); - ConfigurationConditionResolver conditionResolver = new NativeImageConditionResolver(imageClassLoader, ClassInitializationSupport.singleton()); + ConfigurationConditionResolver conditionResolver = new NativeImageConditionResolver(imageClassLoader, ClassInitializationSupport.singleton()); - ProxyConfigurationParser parser = new ProxyConfigurationParser<>(conditionResolver, ConfigurationFiles.Options.getConfigurationParserOptions(), proxyRegistry); + ProxyConfigurationParser parser = new ProxyConfigurationParser<>(conditionResolver, ConfigurationFiles.Options.getConfigurationParserOptions(), proxyRegistry); loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurations(parser, imageClassLoader, "dynamic proxy", ConfigurationFiles.Options.DynamicProxyConfigurationFiles, ConfigurationFiles.Options.DynamicProxyConfigurationResources, ConfigurationFile.DYNAMIC_PROXY.getFileName()); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/proxy/ProxyRegistry.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/proxy/ProxyRegistry.java index f2a2e1093e89..f66469b7a6bf 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/proxy/ProxyRegistry.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/proxy/ProxyRegistry.java @@ -27,14 +27,14 @@ import java.util.List; import java.util.function.BiConsumer; -import org.graalvm.nativeimage.impl.ConfigurationCondition; +import org.graalvm.nativeimage.hosted.InclusionCondition; import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; import com.oracle.svm.hosted.ConditionalConfigurationRegistry; import com.oracle.svm.hosted.ImageClassLoader; import com.oracle.svm.util.LogUtils; -public class ProxyRegistry extends ConditionalConfigurationRegistry implements BiConsumer> { +public class ProxyRegistry extends ConditionalConfigurationRegistry implements BiConsumer> { private final DynamicProxyRegistry dynamicProxySupport; private final ImageClassLoader imageClassLoader; @@ -44,7 +44,7 @@ public ProxyRegistry(DynamicProxyRegistry dynamicProxySupport, ImageClassLoader } @Override - public void accept(ConfigurationCondition condition, List proxies) { + public void accept(InclusionCondition condition, List proxies) { Class[] interfaces = checkIfInterfacesAreValid(proxies); if (interfaces != null) { registerConditionalConfiguration(condition, (cnd) -> { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/serialize/SerializationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/serialize/SerializationFeature.java index 49e27e17a6e3..237f37f73709 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/serialize/SerializationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/serialize/SerializationFeature.java @@ -53,8 +53,8 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; @@ -131,17 +131,17 @@ public void afterRegistration(AfterRegistrationAccess a) { public void duringSetup(DuringSetupAccess a) { FeatureImpl.DuringSetupAccessImpl access = (FeatureImpl.DuringSetupAccessImpl) a; ImageClassLoader imageClassLoader = access.getImageClassLoader(); - ConfigurationConditionResolver conditionResolver = new NativeImageConditionResolver(imageClassLoader, ClassInitializationSupport.singleton()); + ConfigurationConditionResolver conditionResolver = new NativeImageConditionResolver(imageClassLoader, ClassInitializationSupport.singleton()); EnumSet parserOptions = ConfigurationFiles.Options.getConfigurationParserOptions(); - SerializationConfigurationParser parser = SerializationConfigurationParser.create(true, conditionResolver, serializationBuilder, parserOptions); + SerializationConfigurationParser parser = SerializationConfigurationParser.create(true, conditionResolver, serializationBuilder, parserOptions); loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, imageClassLoader, "serialization"); - SerializationConfigurationParser denyCollectorParser = SerializationConfigurationParser.create(false, conditionResolver, serializationDenyRegistry, parserOptions); + SerializationConfigurationParser denyCollectorParser = SerializationConfigurationParser.create(false, conditionResolver, serializationDenyRegistry, parserOptions); ConfigurationParserUtils.parseAndRegisterConfigurations(denyCollectorParser, imageClassLoader, "serialization", ConfigurationFiles.Options.SerializationDenyConfigurationFiles, ConfigurationFiles.Options.SerializationDenyConfigurationResources, ConfigurationFile.SERIALIZATION_DENY.getFileName()); - SerializationConfigurationParser legacyParser = SerializationConfigurationParser.create(false, conditionResolver, serializationBuilder, parserOptions); + SerializationConfigurationParser legacyParser = SerializationConfigurationParser.create(false, conditionResolver, serializationBuilder, parserOptions); loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, imageClassLoader, "serialization", ConfigurationFiles.Options.SerializationConfigurationFiles, ConfigurationFiles.Options.SerializationConfigurationResources, ConfigurationFile.SERIALIZATION.getFileName()); @@ -157,7 +157,7 @@ private static void registerLambdasFromConstantNodesInGraph(StructuredGraph grap if (lambdaClass != null && Serializable.class.isAssignableFrom(lambdaClass)) { RuntimeReflection.register(ReflectionUtil.lookupMethod(lambdaClass, "writeReplace")); SerializationBuilder.registerSerializationUIDElements(lambdaClass, false); - serializationBuilder.serializationSupport.registerSerializationTargetClass(ConfigurationCondition.alwaysTrue(), lambdaClass); + serializationBuilder.serializationSupport.registerSerializationTargetClass(InclusionCondition.alwaysInclude(), lambdaClass); } } } @@ -214,7 +214,7 @@ public static Object getConstructorAccessor(Constructor constructor) { } } -final class SerializationDenyRegistry implements RuntimeSerializationSupport { +final class SerializationDenyRegistry implements RuntimeSerializationSupport { private final Map, Boolean> deniedClasses = new HashMap<>(); private final ConfigurationTypeResolver typeResolver; @@ -228,24 +228,24 @@ final class SerializationDenyRegistry implements RuntimeSerializationSupport clazz) { + public void registerIncludingAssociatedClasses(InclusionCondition condition, Class clazz) { register(condition, clazz); } @Override - public void register(ConfigurationCondition condition, Class clazz) { + public void register(InclusionCondition condition, Class clazz) { if (clazz != null) { deniedClasses.put(clazz, true); } } @Override - public void register(ConfigurationCondition condition, String className) { + public void register(InclusionCondition condition, String className) { this.register(condition, typeResolver.resolveType(className)); } @Override - public void registerLambdaCapturingClass(ConfigurationCondition condition, String lambdaCapturingClassName) { + public void registerLambdaCapturingClass(InclusionCondition condition, String lambdaCapturingClassName) { Class lambdaCapturingClass = typeResolver.resolveType(lambdaCapturingClassName); if (lambdaCapturingClass != null) { deniedClasses.put(lambdaCapturingClass, true); @@ -253,7 +253,7 @@ public void registerLambdaCapturingClass(ConfigurationCondition condition, Strin } @Override - public void registerProxyClass(ConfigurationCondition condition, List implementedInterfaces) { + public void registerProxyClass(InclusionCondition condition, List implementedInterfaces) { } public boolean isAllowed(Class clazz) { @@ -266,7 +266,7 @@ public boolean isAllowed(Class clazz) { } } -final class SerializationBuilder extends ConditionalConfigurationRegistry implements RuntimeSerializationSupport { +final class SerializationBuilder extends ConditionalConfigurationRegistry implements RuntimeSerializationSupport { private static final Method getConstructorAccessorMethod = ReflectionUtil.lookupMethod(Constructor.class, "getConstructorAccessor"); private static final Method getExternalizableConstructorMethod = ReflectionUtil.lookupMethod(ObjectStreamClass.class, "getExternalizableConstructor", Class.class); @@ -309,11 +309,11 @@ private void abortIfSealed() { } @Override - public void registerIncludingAssociatedClasses(ConfigurationCondition condition, Class clazz) { + public void registerIncludingAssociatedClasses(InclusionCondition condition, Class clazz) { registerIncludingAssociatedClasses(condition, clazz, new HashSet<>()); } - private void registerIncludingAssociatedClasses(ConfigurationCondition condition, Class clazz, Set> alreadyVisited) { + private void registerIncludingAssociatedClasses(InclusionCondition condition, Class clazz, Set> alreadyVisited) { if (alreadyVisited.contains(clazz)) { return; } @@ -363,7 +363,7 @@ private void registerIncludingAssociatedClasses(ConfigurationCondition condition } @Override - public void registerLambdaCapturingClass(ConfigurationCondition condition, String lambdaCapturingClassName) { + public void registerLambdaCapturingClass(InclusionCondition condition, String lambdaCapturingClassName) { abortIfSealed(); Class lambdaCapturingClass = typeResolver.resolveType(lambdaCapturingClassName); @@ -385,7 +385,7 @@ public void registerLambdaCapturingClass(ConfigurationCondition condition, Strin } @Override - public void registerProxyClass(ConfigurationCondition condition, List implementedInterfaces) { + public void registerProxyClass(InclusionCondition condition, List implementedInterfaces) { registerConditionalConfiguration(condition, (cnd) -> { Class proxyClass = proxyRegistry.createProxyClassForSerialization(implementedInterfaces); register(cnd, proxyClass); @@ -393,7 +393,7 @@ public void registerProxyClass(ConfigurationCondition condition, List im } @Override - public void register(ConfigurationCondition condition, String targetClassName) { + public void register(InclusionCondition condition, String targetClassName) { abortIfSealed(); Class serializationTargetClass = typeResolver.resolveType(targetClassName); /* With invalid streams we have to register the class for lookup */ @@ -405,14 +405,9 @@ public void register(ConfigurationCondition condition, String targetClassName) { } @Override - public void register(ConfigurationCondition condition, Class serializationTargetClass) { + public void register(InclusionCondition condition, Class serializationTargetClass) { abortIfSealed(); registerConditionalConfiguration(condition, (cnd) -> { - /* - * Register class for reflection as it is needed when the class-value itself is - * serialized. - */ - ImageSingletons.lookup(RuntimeReflectionSupport.class).register(condition, serializationTargetClass); if (!Serializable.class.isAssignableFrom(serializationTargetClass)) { return; @@ -428,9 +423,9 @@ public void register(ConfigurationCondition condition, Class serializationTar Class superclass = serializationTargetClass.getSuperclass(); if (superclass != null) { - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredConstructorsQuery(ConfigurationCondition.alwaysTrue(), true, superclass); - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerMethodLookup(ConfigurationCondition.alwaysTrue(), superclass, "writeReplace"); - ImageSingletons.lookup(RuntimeReflectionSupport.class).registerMethodLookup(ConfigurationCondition.alwaysTrue(), superclass, "readResolve"); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerAllDeclaredConstructorsQuery(cnd, true, superclass); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerMethodLookup(cnd, superclass, "writeReplace"); + ImageSingletons.lookup(RuntimeReflectionSupport.class).registerMethodLookup(cnd, superclass, "readResolve"); } registerForSerialization(cnd, serializationTargetClass); @@ -440,7 +435,7 @@ public void register(ConfigurationCondition condition, Class serializationTar }); } - private void addOrQueueConstructorAccessors(ConfigurationCondition cnd, Class serializationTargetClass) { + private void addOrQueueConstructorAccessors(InclusionCondition cnd, Class serializationTargetClass) { if (pendingConstructorRegistrations != null) { // cannot yet create constructor accessor -> add to pending pendingConstructorRegistrations.add(() -> registerConstructorAccessors(cnd, serializationTargetClass)); @@ -450,7 +445,7 @@ private void addOrQueueConstructorAccessors(ConfigurationCondition cnd, Class } } - private void registerConstructorAccessors(ConfigurationCondition cnd, Class serializationTargetClass) { + private void registerConstructorAccessors(InclusionCondition cnd, Class serializationTargetClass) { serializationSupport.registerSerializationTargetClass(cnd, serializationTargetClass); registerConstructorAccessor(cnd, serializationTargetClass, null); for (Class superclass = serializationTargetClass; superclass != null; superclass = superclass.getSuperclass()) { @@ -458,7 +453,7 @@ private void registerConstructorAccessors(ConfigurationCondition cnd, Class s } } - private void registerConstructorAccessor(ConfigurationCondition cnd, Class serializationTargetClass, Class targetConstructorClass) { + private void registerConstructorAccessor(InclusionCondition cnd, Class serializationTargetClass, Class targetConstructorClass) { Optional.ofNullable(addConstructorAccessor(serializationTargetClass, targetConstructorClass)) .map(ReflectionUtil::lookupConstructor) .ifPresent(methods -> ImageSingletons.lookup(RuntimeReflectionSupport.class).register(cnd, false, methods)); @@ -485,7 +480,7 @@ private static void registerQueriesForInheritableMethod(Class clazz, String m } } - private static void registerMethod(ConfigurationCondition cnd, Class clazz, String methodName, Class... args) { + private static void registerMethod(InclusionCondition cnd, Class clazz, String methodName, Class... args) { Method method = ReflectionUtil.lookupMethod(true, clazz, methodName, args); if (method != null) { ImageSingletons.lookup(RuntimeReflectionSupport.class).register(cnd, false, method); @@ -494,7 +489,7 @@ private static void registerMethod(ConfigurationCondition cnd, Class clazz, S } } - private void registerForSerialization(ConfigurationCondition cnd, Class serializationTargetClass) { + private void registerForSerialization(InclusionCondition cnd, Class serializationTargetClass) { if (Serializable.class.isAssignableFrom(serializationTargetClass)) { /* @@ -569,7 +564,7 @@ public void afterAnalysis() { sealed = true; } - private static void registerForDeserialization(ConfigurationCondition cnd, Class serializationTargetClass) { + private static void registerForDeserialization(InclusionCondition cnd, Class serializationTargetClass) { ImageSingletons.lookup(RuntimeReflectionSupport.class).register(cnd, serializationTargetClass); if (serializationTargetClass.isRecord()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/xml/XMLParsersRegistration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/xml/XMLParsersRegistration.java index 68ca0b5304c0..db36638d30d3 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/xml/XMLParsersRegistration.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/xml/XMLParsersRegistration.java @@ -31,8 +31,8 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.InclusionCondition; import org.graalvm.nativeimage.hosted.RuntimeReflection; -import org.graalvm.nativeimage.impl.ConfigurationCondition; import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport; import com.oracle.svm.configure.ResourcesRegistry; @@ -133,22 +133,22 @@ void registerResources() { ClassInitializationSupport classInitializationSupport = (ClassInitializationSupport) ImageSingletons.lookup(RuntimeClassInitializationSupport.class); classInitializationSupport.setConfigurationSealed(false); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xml.internal.serializer.utils.SerializerMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xml.internal.serializer.Encodings"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xml.internal.serializer.HTMLEntities"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xml.internal.serializer.XMLEntities"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.xpath.regex.message"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.DOMMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.DatatypeMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.JAXPValidationMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.SAXMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.XIncludeMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.XMLMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.XMLSchemaMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.XMLSerializerMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xerces.internal.impl.msg.XPointerMessages"); - ResourcesRegistry.singleton().addResourceBundles(ConfigurationCondition.alwaysTrue(), "com.sun.org.apache.xalan.internal.res.XSLTInfo"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xml.internal.serializer.utils.SerializerMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xml.internal.serializer.Encodings"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xml.internal.serializer.HTMLEntities"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xml.internal.serializer.XMLEntities"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.xpath.regex.message"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.DOMMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.DatatypeMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.JAXPValidationMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.SAXMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.XIncludeMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.XMLMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.XMLSchemaMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.XMLSerializerMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xerces.internal.impl.msg.XPointerMessages"); + ResourcesRegistry.singleton().addResourceBundles(InclusionCondition.alwaysInclude(), "com.sun.org.apache.xalan.internal.res.XSLTInfo"); classInitializationSupport.setConfigurationSealed(true); }