diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/JPMSExportBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/JPMSExportBuildItem.java index 9ddb3ebb378c9..d2bf02220f78d 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/JPMSExportBuildItem.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/JPMSExportBuildItem.java @@ -13,17 +13,22 @@ public final class JPMSExportBuildItem extends MultiBuildItem { private final String moduleName; private final String packageName; private final GraalVM.Version exportAfter; + private final GraalVM.Version exportBefore; public JPMSExportBuildItem(String moduleName, String packageName) { - this.moduleName = moduleName; - this.packageName = packageName; - this.exportAfter = GraalVM.Version.MINIMUM; + this(moduleName, packageName, GraalVM.Version.MINIMUM, null); } public JPMSExportBuildItem(String moduleName, String packageName, GraalVM.Version exportAfter) { + this(moduleName, packageName, exportAfter, null); + } + + public JPMSExportBuildItem(String moduleName, String packageName, GraalVM.Version exportAfter, + GraalVM.Version exportBefore) { this.moduleName = moduleName; this.packageName = packageName; this.exportAfter = exportAfter; + this.exportBefore = exportBefore; } public String getPackage() { @@ -54,4 +59,8 @@ public int hashCode() { public GraalVM.Version getExportAfter() { return exportAfter; } + + public GraalVM.Version getExportBefore() { + return exportBefore; + } } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/GraalVM.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/GraalVM.java index 449654dc80101..08dcb829de7a7 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/GraalVM.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/GraalVM.java @@ -25,7 +25,7 @@ public static final class Version implements Comparable { static final Version VERSION_21_3_0 = new Version("GraalVM 21.3.0", "21.3.0", Distribution.ORACLE); static final Version VERSION_21_3_2 = new Version("GraalVM 21.3.2", "21.3.2", Distribution.ORACLE); static final Version VERSION_22_0_0_2 = new Version("GraalVM 22.0.0.2", "22.0.0.2", Distribution.ORACLE); - static final Version VERSION_22_3_0 = new Version("GraalVM 22.3.0", "22.3.0", Distribution.ORACLE); + public static final Version VERSION_22_3_0 = new Version("GraalVM 22.3.0", "22.3.0", Distribution.ORACLE); public static final Version VERSION_22_1_0 = new Version("GraalVM 22.1.0", "22.1.0", Distribution.ORACLE); static final Version VERSION_22_2_0 = new Version("GraalVM 22.2.0", "22.2.0", Distribution.ORACLE); diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java index 54e349a716c59..19563e335b3de 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java @@ -857,7 +857,9 @@ public NativeImageInvokerInfo build() { if (jpmsExports != null) { HashSet deduplicatedJpmsExport = new HashSet<>(jpmsExports); for (JPMSExportBuildItem jpmsExport : deduplicatedJpmsExport) { - if (graalVMVersion.isNewerThan(jpmsExport.getExportAfter())) { + GraalVM.Version exportBeforeVersion = jpmsExport.getExportBefore(); + if (graalVMVersion.isNewerThan(jpmsExport.getExportAfter()) && + (exportBeforeVersion == null || graalVMVersion.isOlderThan(exportBeforeVersion))) { nativeImageArgs.add( "-J--add-exports=" + jpmsExport.getModule() + "/" + jpmsExport.getPackage() + "=ALL-UNNAMED"); 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 87c5a555557d1..3abd0a1eac2b2 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 @@ -43,6 +43,8 @@ import io.quarkus.deployment.builditem.nativeimage.UnsafeAccessedFieldBuildItem; import io.quarkus.deployment.pkg.steps.GraalVM; import io.quarkus.gizmo.AssignableResultHandle; +import io.quarkus.gizmo.BranchResult; +import io.quarkus.gizmo.BytecodeCreator; import io.quarkus.gizmo.CatchBlockCreator; import io.quarkus.gizmo.ClassCreator; import io.quarkus.gizmo.ClassOutput; @@ -57,6 +59,8 @@ public class NativeImageFeatureStep { public static final String GRAAL_FEATURE = "io.quarkus.runner.Feature"; + private static final MethodDescriptor VERSION_CURRENT = ofMethod(Version.class, "getCurrent", Version.class); + private static final MethodDescriptor VERSION_COMPARE_TO = ofMethod(Version.class, "compareTo", int.class, int[].class); private static final MethodDescriptor IMAGE_SINGLETONS_LOOKUP = ofMethod(ImageSingletons.class, "lookup", Object.class, Class.class); @@ -89,7 +93,8 @@ public class NativeImageFeatureStep { private static final MethodDescriptor INVOKE = ofMethod( Method.class, "invoke", Object.class, Object.class, Object[].class); static final String RUNTIME_REFLECTION = RuntimeReflection.class.getName(); - static final String JNI_RUNTIME_ACCESS = "com.oracle.svm.core.jni.JNIRuntimeAccess"; + static final String LEGACY_JNI_RUNTIME_ACCESS = "com.oracle.svm.core.jni.JNIRuntimeAccess"; + static final String JNI_RUNTIME_ACCESS = "org.graalvm.nativeimage.hosted.RuntimeJNIAccess"; static final String BEFORE_ANALYSIS_ACCESS = Feature.BeforeAnalysisAccess.class.getName(); static final String DURING_SETUP_ACCESS = Feature.DuringSetupAccess.class.getName(); static final String DYNAMIC_PROXY_REGISTRY = "com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry"; @@ -124,10 +129,10 @@ void addExportsToNativeImage(BuildProducer features, // required in order to access org.graalvm.nativeimage.impl.RuntimeSerializationSupport and org.graalvm.nativeimage.impl.ConfigurationCondition features.produce( new JPMSExportBuildItem("org.graalvm.sdk", "org.graalvm.nativeimage.impl", GraalVM.Version.VERSION_22_1_0)); - // required in order to access com.oracle.svm.core.jni.JNIRuntimeAccess + // required in order to access com.oracle.svm.core.jni.JNIRuntimeAccess in GraalVM 22.2.x if (jniRuntimeAccessibleClasses != null && !jniRuntimeAccessibleClasses.isEmpty()) { features.produce(new JPMSExportBuildItem("org.graalvm.nativeimage.builder", "com.oracle.svm.core.jni", - GraalVM.Version.VERSION_22_1_0)); + GraalVM.Version.VERSION_22_1_0, GraalVM.Version.VERSION_22_3_0)); } } @@ -547,26 +552,52 @@ public void write(String s, byte[] bytes) { ResultHandle carray = tc.newArray(Class.class, tc.load(1)); tc.writeArrayValue(carray, 0, clazz); - tc.invokeStaticMethod(ofMethod(JNI_RUNTIME_ACCESS, "register", void.class, Class[].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 */ + BytecodeCreator greaterThan22_2 = graalVm22_3Test.trueBranch(); + greaterThan22_2.invokeStaticMethod(ofMethod(JNI_RUNTIME_ACCESS, "register", void.class, Class[].class), carray); if (jniAccessible.isConstructors()) { - tc.invokeStaticMethod( + greaterThan22_2.invokeStaticMethod( ofMethod(JNI_RUNTIME_ACCESS, "register", void.class, Executable[].class), constructors); } if (jniAccessible.isMethods()) { - tc.invokeStaticMethod( + greaterThan22_2.invokeStaticMethod( ofMethod(JNI_RUNTIME_ACCESS, "register", void.class, Executable[].class), methods); } if (jniAccessible.isFields()) { - tc.invokeStaticMethod( - ofMethod(JNI_RUNTIME_ACCESS, "register", void.class, - boolean.class, Field[].class), - tc.load(jniAccessible.isFinalFieldsWriteable()), fields); + greaterThan22_2.invokeStaticMethod( + ofMethod(JNI_RUNTIME_ACCESS, "register", void.class, Field[].class), + fields); + } + /* GraalVM < 22.3 */ + BytecodeCreator smallerThan22_3 = graalVm22_3Test.falseBranch(); + smallerThan22_3.invokeStaticMethod(ofMethod(LEGACY_JNI_RUNTIME_ACCESS, "register", void.class, Class[].class), + carray); + + if (jniAccessible.isConstructors()) { + smallerThan22_3.invokeStaticMethod( + ofMethod(LEGACY_JNI_RUNTIME_ACCESS, "register", void.class, Executable[].class), + constructors); + } + + if (jniAccessible.isMethods()) { + smallerThan22_3.invokeStaticMethod( + ofMethod(LEGACY_JNI_RUNTIME_ACCESS, "register", void.class, Executable[].class), + methods); + } + + if (jniAccessible.isFields()) { + smallerThan22_3.invokeStaticMethod( + ofMethod(LEGACY_JNI_RUNTIME_ACCESS, "register", void.class, boolean.class, Field[].class), + smallerThan22_3.load(jniAccessible.isFinalFieldsWriteable()), fields); } CatchBlockCreator cc = tc.addCatch(Throwable.class);