From 3a0599d11083453d4bc962851f365e32369fc96e Mon Sep 17 00:00:00 2001 From: Gwenneg Lepage Date: Thu, 14 Nov 2019 22:15:01 +0100 Subject: [PATCH] Introduce UnsafeAccessedFieldBuildItem --- .../UnsafeAccessedFieldBuildItem.java | 22 +++++++++++++++++++ .../steps/NativeImageAutoFeatureStep.java | 20 ++++++++++++++++- .../netty/deployment/NettyProcessor.java | 11 ++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/UnsafeAccessedFieldBuildItem.java diff --git a/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/UnsafeAccessedFieldBuildItem.java b/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/UnsafeAccessedFieldBuildItem.java new file mode 100644 index 0000000000000..b8ba486d7d00c --- /dev/null +++ b/core/deployment/src/main/java/io/quarkus/deployment/builditem/nativeimage/UnsafeAccessedFieldBuildItem.java @@ -0,0 +1,22 @@ +package io.quarkus.deployment.builditem.nativeimage; + +import io.quarkus.builder.item.MultiBuildItem; + +public final class UnsafeAccessedFieldBuildItem extends MultiBuildItem { + + final String declaringClass; + final String fieldName; + + public UnsafeAccessedFieldBuildItem(String declaringClass, String fieldName) { + this.declaringClass = declaringClass; + this.fieldName = fieldName; + } + + public String getDeclaringClass() { + return declaringClass; + } + + public String getFieldName() { + return fieldName; + } +} diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageAutoFeatureStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageAutoFeatureStep.java index bb0eae4e81412..794114ce1b76d 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageAutoFeatureStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageAutoFeatureStep.java @@ -32,6 +32,7 @@ import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; +import io.quarkus.deployment.builditem.nativeimage.UnsafeAccessedFieldBuildItem; import io.quarkus.gizmo.CatchBlockCreator; import io.quarkus.gizmo.ClassCreator; import io.quarkus.gizmo.ClassOutput; @@ -65,7 +66,8 @@ void generateFeature(BuildProducer nativeIma List reflectiveMethods, List reflectiveFields, List reflectiveClassBuildItems, - List serviceProviderBuildItems) { + List serviceProviderBuildItems, + List unsafeAccessedFields) { ClassCreator file = new ClassCreator(new ClassOutput() { @Override public void write(String s, byte[] bytes) { @@ -80,6 +82,22 @@ public void write(String s, byte[] bytes) { TryBlock overallCatch = beforeAn.tryBlock(); //TODO: at some point we are going to need to break this up, as if it get too big it will hit the method size limit + ResultHandle beforeAnalysisParam = beforeAn.getMethodParam(0); + for (UnsafeAccessedFieldBuildItem unsafeAccessedField : unsafeAccessedFields) { + TryBlock tc = overallCatch.tryBlock(); + ResultHandle declaringClassHandle = tc.invokeStaticMethod( + ofMethod(Class.class, "forName", Class.class, String.class), + tc.load(unsafeAccessedField.getDeclaringClass())); + ResultHandle fieldHandle = tc.invokeVirtualMethod( + ofMethod(Class.class, "getDeclaredField", Field.class, String.class), declaringClassHandle, + tc.load(unsafeAccessedField.getFieldName())); + tc.invokeInterfaceMethod( + ofMethod(Feature.BeforeAnalysisAccess.class, "registerAsUnsafeAccessed", void.class, Field.class), + beforeAnalysisParam, fieldHandle); + CatchBlockCreator cc = tc.addCatch(Throwable.class); + cc.invokeVirtualMethod(ofMethod(Throwable.class, "printStackTrace", void.class), cc.getCaughtException()); + } + ResultHandle initSingleton = overallCatch.invokeStaticMethod(IMAGE_SINGLETONS_LOOKUP, overallCatch.loadClass(RuntimeClassInitializationSupport.class)); ResultHandle quarkus = overallCatch.load("Quarkus"); diff --git a/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java b/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java index eeb45c76e2c27..0e9bdc8bb9957 100644 --- a/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java +++ b/extensions/netty/deployment/src/main/java/io/quarkus/netty/deployment/NettyProcessor.java @@ -1,5 +1,7 @@ package io.quarkus.netty.deployment; +import java.util.Arrays; +import java.util.List; import java.util.Optional; import java.util.function.Supplier; @@ -21,6 +23,7 @@ import io.quarkus.deployment.builditem.nativeimage.NativeImageSystemPropertyBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.UnsafeAccessedFieldBuildItem; import io.quarkus.netty.BossEventLoopGroup; import io.quarkus.netty.MainEventLoopGroup; import io.quarkus.netty.runtime.NettyRecorder; @@ -177,4 +180,12 @@ public RuntimeReinitializedClassBuildItem reinitScheduledFutureTask() { return new RuntimeReinitializedClassBuildItem( "io.quarkus.netty.runtime.graal.Holder_io_netty_util_concurrent_ScheduledFutureTask"); } + + // TODO: Remove this when netty.version is 4.1.43.Final or greater. + @BuildStep + public List unsafeAccessedFields() { + return Arrays.asList( + new UnsafeAccessedFieldBuildItem("sun.nio.ch.SelectorImpl", "selectedKeys"), + new UnsafeAccessedFieldBuildItem("sun.nio.ch.SelectorImpl", "publicSelectedKeys")); + } }