Skip to content

Commit

Permalink
Introduce new JPMS exports to allow running native-image on module-path
Browse files Browse the repository at this point in the history
Once oracle/graal#4468 gets merged, native-image
will run on module-path requiring some additional exports to be passed
to it in order to access internal APIs.
  • Loading branch information
zakkak committed Jun 15, 2022
1 parent e644ded commit 6ddd964
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.deployment.builditem.nativeimage;

import java.util.Objects;

import io.quarkus.builder.item.MultiBuildItem;

/**
Expand All @@ -22,4 +24,21 @@ public String getPackage() {
public String getModule() {
return moduleName;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
JPMSExportBuildItem that = (JPMSExportBuildItem) o;
return moduleName.equals(that.moduleName) && packageName.equals(that.packageName);
}

@Override
public int hashCode() {
return Objects.hash(moduleName, packageName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand All @@ -23,6 +24,7 @@
import org.jboss.logging.Logger;

import io.quarkus.bootstrap.util.IoUtils;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.nativeimage.ExcludeConfigBuildItem;
import io.quarkus.deployment.builditem.nativeimage.JPMSExportBuildItem;
Expand Down Expand Up @@ -73,6 +75,12 @@ public class NativeImageBuildStep {
private static final String MOVED_TRUST_STORE_NAME = "trustStore";
public static final String APP_SOURCES = "app-sources";

@BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)
void addExportsToNativeImage(BuildProducer<JPMSExportBuildItem> exports) {
// Needed by io.quarkus.runtime.ResourceHelper.registerResources
exports.produce(new JPMSExportBuildItem("org.graalvm.nativeimage.builder", "com.oracle.svm.core.jdk"));
}

@BuildStep(onlyIf = NativeBuild.class)
ArtifactResultBuildItem result(NativeImageBuildItem image) {
NativeImageBuildItem.GraalVMVersion graalVMVersion = image.getGraalVMInfo();
Expand Down Expand Up @@ -807,7 +815,8 @@ public NativeImageInvokerInfo build() {
}

if (jpmsExports != null) {
for (JPMSExportBuildItem jpmsExport : jpmsExports) {
HashSet<JPMSExportBuildItem> deduplicatedJpmsExport = new HashSet<>(jpmsExports);
for (JPMSExportBuildItem jpmsExport : deduplicatedJpmsExport) {
nativeImageArgs.add(
"-J--add-exports=" + jpmsExport.getModule() + "/" + jpmsExport.getPackage() + "=ALL-UNNAMED");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.quarkus.deployment.builditem.GeneratedNativeImageClassBuildItem;
import io.quarkus.deployment.builditem.GeneratedResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ForceNonWeakReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.JPMSExportBuildItem;
import io.quarkus.deployment.builditem.nativeimage.JniRuntimeAccessBuildItem;
import io.quarkus.deployment.builditem.nativeimage.LambdaCapturingTypeBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageProxyDefinitionBuildItem;
Expand Down Expand Up @@ -116,8 +117,18 @@ GeneratedResourceBuildItem generateNativeResourcesList(List<NativeImageResourceB
sb.toString().getBytes(StandardCharsets.UTF_8));
}

@BuildStep
JPMSExportBuildItem addExportsToNativeImage(List<JniRuntimeAccessBuildItem> jniRuntimeAccessibleClasses) {
// required in order to access com.oracle.svm.core.jni.JNIRuntimeAccess
if (jniRuntimeAccessibleClasses != null && !jniRuntimeAccessibleClasses.isEmpty()) {
return new JPMSExportBuildItem("org.graalvm.nativeimage.builder", "com.oracle.svm.core.jni");
}
return null;
}

@BuildStep
void generateFeature(BuildProducer<GeneratedNativeImageClassBuildItem> nativeImageClass,
BuildProducer<JPMSExportBuildItem> exports,
List<RuntimeInitializedClassBuildItem> runtimeInitializedClassBuildItems,
List<RuntimeInitializedPackageBuildItem> runtimeInitializedPackageBuildItems,
List<RuntimeReinitializedClassBuildItem> runtimeReinitializedClassBuildItems,
Expand Down Expand Up @@ -239,6 +250,9 @@ public void write(String s, byte[] bytes) {
}

if (!proxies.isEmpty()) {
// Needed to access DYNAMIC_PROXY_REGISTRY
exports.produce(new JPMSExportBuildItem("org.graalvm.nativeimage.builder", "com.oracle.svm.core.jdk.proxy"));

ResultHandle proxySupportClass = overallCatch.loadClassFromTCCL(DYNAMIC_PROXY_REGISTRY);
ResultHandle proxySupport = overallCatch.invokeStaticMethod(
IMAGE_SINGLETONS_LOOKUP,
Expand All @@ -259,6 +273,9 @@ public void write(String s, byte[] bytes) {

/* Resource includes and excludes */
if (!resourcePatterns.isEmpty()) {
// Needed to access LOOKUP_METHOD
exports.produce(new JPMSExportBuildItem("org.graalvm.nativeimage.base", "com.oracle.svm.util"));

ResultHandle resourcesRegistrySingleton = overallCatch.invokeStaticMethod(IMAGE_SINGLETONS_LOOKUP,
overallCatch.loadClassFromTCCL("com.oracle.svm.core.configure.ResourcesRegistry"));
TryBlock tc = overallCatch.tryBlock();
Expand Down Expand Up @@ -316,6 +333,9 @@ public void write(String s, byte[] bytes) {
}

if (!resourceBundles.isEmpty()) {
// Needed to access LOCALIZATION_FEATURE
exports.produce(new JPMSExportBuildItem("org.graalvm.nativeimage.builder", "com.oracle.svm.core.jdk.localization"));

AssignableResultHandle registerMethod = overallCatch.createVariable(Method.class);
AssignableResultHandle locClass = overallCatch.createVariable(Class.class);
TryBlock locTryBlock = overallCatch.tryBlock();
Expand Down Expand Up @@ -474,6 +494,8 @@ public void write(String s, byte[] bytes) {

if (entry.getValue().serialization) {
if (registerSerializationMethod == null) {
// Needed by createRegisterSerializationForClassMethod to access LOOKUP_METHOD
exports.produce(new JPMSExportBuildItem("org.graalvm.nativeimage.base", "com.oracle.svm.util"));
registerSerializationMethod = createRegisterSerializationForClassMethod(file);
}

Expand Down

0 comments on commit 6ddd964

Please sign in to comment.