diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageFeatureStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageFeatureStep.java index 14d1b6933b108..5687cc9487327 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageFeatureStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageFeatureStep.java @@ -2,7 +2,6 @@ import static io.quarkus.gizmo.MethodDescriptor.ofMethod; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; @@ -15,10 +14,12 @@ import java.util.Map; import java.util.Set; +import org.graalvm.home.Version; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.RuntimeClassInitialization; import org.graalvm.nativeimage.hosted.RuntimeReflection; +import org.graalvm.nativeimage.impl.ConfigurationCondition; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -99,6 +100,7 @@ public class NativeImageFeatureStep { static final String DURING_SETUP_ACCESS = Feature.DuringSetupAccess.class.getName(); static final String DYNAMIC_PROXY_REGISTRY = "com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry"; static final String LOCALIZATION_FEATURE = "com.oracle.svm.core.jdk.localization.LocalizationFeature"; + static final String RUNTIME_RESOURCE_SUPPORT = "org.graalvm.nativeimage.impl.RuntimeResourceSupport"; public static final MethodDescriptor WEAK_REFLECTION_REGISTRATION = MethodDescriptor.ofMethod(WeakReflection.class, "register", void.class, Feature.BeforeAnalysisAccess.class, Class.class, boolean.class, boolean.class, boolean.class); @@ -286,55 +288,63 @@ public void write(String s, byte[] bytes) { /* Resource includes and excludes */ if (!resourcePatterns.isEmpty()) { - // Needed to access com.oracle.svm.core.configure.ResourcesRegistry.* + // Needed to access com.oracle.svm.core.configure.ResourcesRegistry.* in GraalVM 22.2 exports.produce(new JPMSExportBuildItem("org.graalvm.nativeimage.builder", "com.oracle.svm.core.configure", - GraalVM.Version.VERSION_22_1_0)); + GraalVM.Version.VERSION_22_1_0, GraalVM.Version.VERSION_22_3_0)); - ResultHandle resourcesRegistrySingleton = overallCatch.invokeStaticMethod(IMAGE_SINGLETONS_LOOKUP, - overallCatch.loadClassFromTCCL("com.oracle.svm.core.configure.ResourcesRegistry")); TryBlock tc = overallCatch.tryBlock(); - ResultHandle currentThread = tc.invokeStaticMethod(ofMethod(Thread.class, "currentThread", Thread.class)); - ResultHandle tccl = tc.invokeVirtualMethod(ofMethod(Thread.class, "getContextClassLoader", ClassLoader.class), - currentThread); - AssignableResultHandle resourcesArgTypes = tc.createVariable(Class[].class); + ResultHandle resourcesArgTypes = tc.marshalAsArray(Class.class, tc.loadClassFromTCCL(ConfigurationCondition.class), + tc.loadClassFromTCCL(String.class)); AssignableResultHandle resourcesArgs = tc.createVariable(Object[].class); - AssignableResultHandle argsIndex = tc.createVariable(int.class); - - ResultHandle argTypes = tc.newArray(Class.class, tc.load(2)); - ResultHandle configurationConditionClass = tc.invokeStaticMethod(FOR_NAME, - tc.load("org.graalvm.nativeimage.impl.ConfigurationCondition"), - tc.load(false), tccl); - tc.writeArrayValue(argTypes, 0, configurationConditionClass); - tc.writeArrayValue(argTypes, 1, tc.loadClassFromTCCL(String.class)); - tc.assign(resourcesArgTypes, argTypes); - ResultHandle args = tc.newArray(Object.class, tc.load(2)); - ResultHandle alwaysTrueMethod = tc.invokeStaticMethod(LOOKUP_METHOD, - configurationConditionClass, - tc.load("alwaysTrue"), - tc.newArray(Class.class, tc.load(0))); - ResultHandle alwaysTrueResult = tc.invokeVirtualMethod(INVOKE, - alwaysTrueMethod, tc.loadNull(), - tc.newArray(Object.class, tc.load(0))); - tc.writeArrayValue(args, 0, alwaysTrueResult); - tc.assign(resourcesArgs, args); - tc.assign(argsIndex, tc.load(1)); - - ResultHandle ignoreResourcesMethod = tc.invokeStaticMethod(LOOKUP_METHOD, - tc.loadClassFromTCCL("com.oracle.svm.core.configure.ResourcesRegistry"), - tc.load("ignoreResources"), resourcesArgTypes); - ResultHandle addResourcesMethod = tc.invokeStaticMethod(LOOKUP_METHOD, - tc.loadClassFromTCCL("com.oracle.svm.core.configure.ResourcesRegistry"), - tc.load("addResources"), resourcesArgTypes); + tc.assign(resourcesArgs, + tc.marshalAsArray(Object.class, tc.invokeStaticMethod(CONFIGURATION_ALWAYS_TRUE), tc.loadNull())); + + AssignableResultHandle ignoreResourcesMethod = tc.createVariable(Method.class); + AssignableResultHandle addResourcesMethod = tc.createVariable(Method.class); + AssignableResultHandle resourcesSingleton = tc.createVariable(Object.class); + + BranchResult graalVm22_3Test = tc.ifGreaterEqualZero(tc.invokeVirtualMethod(VERSION_COMPARE_TO, + tc.invokeStaticMethod(VERSION_CURRENT), + tc.marshalAsArray(int.class, tc.load(22), tc.load(3)))); + /* GraalVM >= 22.3 */ + try (BytecodeCreator greaterThan22_2 = graalVm22_3Test.trueBranch()) { + + ResultHandle runtimeResourceSupportClass = greaterThan22_2.loadClassFromTCCL(RUNTIME_RESOURCE_SUPPORT); + + greaterThan22_2.assign(resourcesSingleton, greaterThan22_2.invokeStaticMethod(IMAGE_SINGLETONS_LOOKUP, + runtimeResourceSupportClass)); + + greaterThan22_2.assign(ignoreResourcesMethod, greaterThan22_2.invokeStaticMethod(LOOKUP_METHOD, + runtimeResourceSupportClass, greaterThan22_2.load("ignoreResources"), resourcesArgTypes)); + greaterThan22_2.assign(addResourcesMethod, greaterThan22_2.invokeStaticMethod(LOOKUP_METHOD, + runtimeResourceSupportClass, greaterThan22_2.load("addResources"), resourcesArgTypes)); + } + + /* GraalVM < 22.3 */ + try (BytecodeCreator smallerThan22_3 = graalVm22_3Test.falseBranch()) { + + ResultHandle resourceRegistryClass = smallerThan22_3 + .loadClassFromTCCL("com.oracle.svm.core.configure.ResourcesRegistry"); + smallerThan22_3.assign(resourcesSingleton, smallerThan22_3.invokeStaticMethod(IMAGE_SINGLETONS_LOOKUP, + resourceRegistryClass)); + + smallerThan22_3.assign(ignoreResourcesMethod, smallerThan22_3.invokeStaticMethod(LOOKUP_METHOD, + resourceRegistryClass, smallerThan22_3.load("ignoreResources"), resourcesArgTypes)); + smallerThan22_3.assign(addResourcesMethod, smallerThan22_3.invokeStaticMethod(LOOKUP_METHOD, + resourceRegistryClass, smallerThan22_3.load("addResources"), resourcesArgTypes)); + } + + ResultHandle indexOne = tc.load(1); for (NativeImageResourcePatternsBuildItem resourcePatternsItem : resourcePatterns) { for (String pattern : resourcePatternsItem.getExcludePatterns()) { - tc.writeArrayValue(resourcesArgs, argsIndex, tc.load(pattern)); - tc.invokeVirtualMethod(INVOKE, ignoreResourcesMethod, resourcesRegistrySingleton, resourcesArgs); + tc.writeArrayValue(resourcesArgs, indexOne, tc.load(pattern)); + tc.invokeVirtualMethod(INVOKE, ignoreResourcesMethod, resourcesSingleton, resourcesArgs); } for (String pattern : resourcePatternsItem.getIncludePatterns()) { - tc.writeArrayValue(resourcesArgs, argsIndex, tc.load(pattern)); - tc.invokeVirtualMethod(INVOKE, addResourcesMethod, resourcesRegistrySingleton, resourcesArgs); + tc.writeArrayValue(resourcesArgs, indexOne, tc.load(pattern)); + tc.invokeVirtualMethod(INVOKE, addResourcesMethod, resourcesSingleton, resourcesArgs); } } CatchBlockCreator cc = tc.addCatch(Throwable.class); @@ -350,19 +360,53 @@ public void write(String s, byte[] bytes) { // Needed to access LOCALIZATION_FEATURE exports.produce( new JPMSExportBuildItem("org.graalvm.nativeimage.builder", "com.oracle.svm.core.jdk.localization", - GraalVM.Version.VERSION_22_1_0)); + GraalVM.Version.VERSION_22_1_0, GraalVM.Version.VERSION_22_3_0)); + + BranchResult graalVm22_3Test = overallCatch.ifGreaterEqualZero(overallCatch.invokeVirtualMethod(VERSION_COMPARE_TO, + overallCatch.invokeStaticMethod(VERSION_CURRENT), + overallCatch.marshalAsArray(int.class, overallCatch.load(22), overallCatch.load(3)))); + /* GraalVM >= 22.3 */ + BytecodeCreator greaterThan22_2 = graalVm22_3Test.trueBranch(); + + ResultHandle runtimeResourceSupportClass = greaterThan22_2.loadClassFromTCCL(RUNTIME_RESOURCE_SUPPORT); + ResultHandle addResourceBundlesParams = greaterThan22_2.marshalAsArray(Class.class, + greaterThan22_2.loadClassFromTCCL(ConfigurationCondition.class), + greaterThan22_2.loadClassFromTCCL(String.class)); + ResultHandle addResourceBundlesMethod = greaterThan22_2.invokeStaticMethod( + LOOKUP_METHOD, + runtimeResourceSupportClass, greaterThan22_2.load("addResourceBundles"), addResourceBundlesParams); + ResultHandle runtimeResourceSupport = greaterThan22_2.invokeStaticMethod( + IMAGE_SINGLETONS_LOOKUP, + runtimeResourceSupportClass); + ResultHandle configAlwaysTrue = greaterThan22_2.invokeStaticMethod(CONFIGURATION_ALWAYS_TRUE); + + for (NativeImageResourceBundleBuildItem i : resourceBundles) { + TryBlock et = greaterThan22_2.tryBlock(); - ResultHandle locClass = overallCatch.loadClassFromTCCL(LOCALIZATION_FEATURE); - ResultHandle newParams = overallCatch.marshalAsArray(Class.class, overallCatch.loadClassFromTCCL(String.class)); - ResultHandle registerMethod = overallCatch.invokeVirtualMethod( + et.invokeVirtualMethod( + INVOKE, + addResourceBundlesMethod, runtimeResourceSupport, + et.marshalAsArray(Object.class, configAlwaysTrue, et.load(i.getBundleName()))); + CatchBlockCreator c = et.addCatch(Throwable.class); + //c.invokeVirtualMethod(ofMethod(Throwable.class, "printStackTrace", void.class), c.getCaughtException()); + } + + /* GraalVM < 22.3 */ + BytecodeCreator smallerThan22_3 = graalVm22_3Test.falseBranch(); + + ResultHandle locClass = smallerThan22_3.loadClassFromTCCL(LOCALIZATION_FEATURE); + ResultHandle newParams = smallerThan22_3.marshalAsArray(Class.class, + smallerThan22_3.loadClassFromTCCL(String.class)); + ResultHandle registerMethod = smallerThan22_3.invokeStaticMethod( LOOKUP_METHOD, - locClass, overallCatch.load("prepareBundle"), newParams); + locClass, smallerThan22_3.load("prepareBundle"), newParams); - ResultHandle locSupport = overallCatch.invokeStaticMethod( + ResultHandle locSupport = smallerThan22_3.invokeStaticMethod( IMAGE_SINGLETONS_LOOKUP, locClass); + for (NativeImageResourceBundleBuildItem i : resourceBundles) { - TryBlock et = overallCatch.tryBlock(); + TryBlock et = smallerThan22_3.tryBlock(); et.invokeVirtualMethod(ofMethod(Method.class, "invoke", Object.class, Object.class, Object[].class), registerMethod, locSupport, et.marshalAsArray(Object.class, et.load(i.getBundleName())));