According to this PR https://github.com/netty/netty/pull/9631 Netty should work with JDK +9 with Graal but it doesn't work with Micronaut when using JDK11.
Steps to reproduce the issue:
git clone https://github.com/micronaut-graal-tests/micronaut-basic-appcd micronaut-basic-appgit checkout jdk11./build-native-image.sh./basic-appError:
18:09:13.631 [main] DEBUG i.m.web.router.DefaultRouteBuilder - Created Route: GET /hello/{name} -> HelloController#Single sayHi(String name) (application/json )
18:09:13.632 [main] DEBUG i.m.web.router.DefaultRouteBuilder - Created Route: HEAD /hello/{name} -> HelloController#Single sayHi(String name) (application/json )
18:09:13.642 [main] ERROR io.micronaut.runtime.Micronaut - Error starting Micronaut server: The offset of private final java.util.Set sun.nio.ch.SelectorImpl.selectedKeys is accessed without the field being first registered as unsafe accessed. Please register the field as unsafe accessed. You can do so with a reflection configuration that contains an entry for the field with the attribute "allowUnsafeAccess": true. Such a configuration file can be generated for you. Read CONFIGURE.md and REFLECTION.md for details.
com.oracle.svm.core.jdk.UnsupportedFeatureError: The offset of private final java.util.Set sun.nio.ch.SelectorImpl.selectedKeys is accessed without the field being first registered as unsafe accessed. Please register the field as unsafe accessed. You can do so with a reflection configuration that contains an entry for the field with the attribute "allowUnsafeAccess": true. Such a configuration file can be generated for you. Read CONFIGURE.md and REFLECTION.md for details.
at com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:101)
at jdk.internal.misc.Unsafe.objectFieldOffset(Unsafe.java:50)
at sun.misc.Unsafe.objectFieldOffset(Unsafe.java:640)
at io.netty.util.internal.PlatformDependent0.objectFieldOffset(PlatformDependent0.java:505)
at io.netty.util.internal.PlatformDependent.objectFieldOffset(PlatformDependent.java:651)
at io.netty.channel.nio.NioEventLoop$4.run(NioEventLoop.java:225)
at java.security.AccessController.doPrivileged(AccessController.java:80)
at io.netty.channel.nio.NioEventLoop.openSelector(NioEventLoop.java:215)
at io.netty.channel.nio.NioEventLoop.<init>(NioEventLoop.java:147)
at io.netty.channel.nio.NioEventLoopGroup.newChild(NioEventLoopGroup.java:138)
at io.netty.channel.nio.NioEventLoopGroup.newChild(NioEventLoopGroup.java:37)
at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:84)
at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:58)
at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:47)
at io.netty.channel.MultithreadEventLoopGroup.<init>(MultithreadEventLoopGroup.java:59)
at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:78)
at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:73)
at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:60)
at io.micronaut.http.server.netty.NioEventLoopGroupFactory.createEventLoopGroup(NioEventLoopGroupFactory.java:70)
at io.micronaut.http.server.netty.NettyHttpServer.newEventLoopGroup(NettyHttpServer.java:536)
at io.micronaut.http.server.netty.NettyHttpServer.createWorkerEventLoopGroup(NettyHttpServer.java:427)
at io.micronaut.http.server.netty.NettyHttpServer.start(NettyHttpServer.java:265)
at io.micronaut.http.server.netty.NettyHttpServer.start(NettyHttpServer.java:97)
at io.micronaut.runtime.Micronaut.lambda$start$2(Micronaut.java:70)
at java.util.Optional.ifPresent(Optional.java:183)
at io.micronaut.runtime.Micronaut.start(Micronaut.java:68)
at io.micronaut.runtime.Micronaut.run(Micronaut.java:294)
at io.micronaut.runtime.Micronaut.run(Micronaut.java:280)
at example.micronaut.Application.main(Application.java:8)
Please not that Micronaut version 1.3.0.BUILD-SNAPSHOT used in that branch already includes Netty 4.1.43 (https://github.com/micronaut-projects/micronaut-core/blob/master/gradle.properties#L83) which contain the fix mentioned in https://github.com/netty/netty/pull/9631
The problem is this config
{
"name" : "sun.nio.ch.SelectorImpl",
"allDeclaredFields" : true,
"allDeclaredConstructors" : true
}
in file basic-app-0.1-all.jar!/META-INF/native-image/io.micronaut/http-netty-channel/reflection-config.json. It overrides the allowUnsafeAccess flag from the Netty config. The reflection configs are processed in the order they appear on the command line.
Thank you so much. I'll fix that in Micronaut.
To avoid this kind of errors on our side in the future, is there a way to display all the parameters "collected" from the jars that are used by native-image tool?
If you run native-image with --verbose you should see all the processed /native-image.properties files as well as the command line built from all the collected parameters. For your example code you can see the multiple -H:ReflectionConfigurationResources=... entries:
$ native-image --verbose --no-server --static --no-fallback --class-path build/libs/basic-app-*-all.jar
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/common/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/buffer/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/transport/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/handler/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/codec-http/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.micronaut.http/mime-types/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.micronaut/inject/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.micronaut/http/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.micronaut/netty/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.micronaut/http-netty-channel/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.micronaut/runtime-graal/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/io.micronaut/health/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/example/micronaut/basic-application/native-image.properties
Apply jar:file://~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar!/META-INF/native-image/example/micronaut/native-image.properties
Executing [
~/vm/graalvm-ee-java11-19.3.0/bin/java \
-XX:+UnlockExperimentalVMOptions \
-XX:+EnableJVMCI \
-Dtruffle.TrustAllTruffleRuntimeProviders=true \
-Dtruffle.TruffleRuntime=com.oracle.truffle.api.impl.DefaultTruffleRuntime \
-Dgraalvm.ForcePolyglotInvalid=true \
-Dgraalvm.locatorDisabled=true \
-Dsubstratevm.IgnoreGraalVersionCheck=true \
-Djava.lang.invoke.stringConcat=BC_SB \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.runtime=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.aarch64=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.amd64=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.hotspot=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.services=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.common=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.code.site=ALL-UNNAMED \
--add-exports \
jdk.internal.vm.ci/jdk.vm.ci.code.stack=ALL-UNNAMED \
--add-opens \
jdk.internal.vm.compiler/org.graalvm.compiler.debug=ALL-UNNAMED \
--add-opens \
jdk.internal.vm.compiler/org.graalvm.compiler.nodes=ALL-UNNAMED \
--add-opens \
jdk.unsupported/sun.reflect=ALL-UNNAMED \
--add-opens \
java.base/jdk.internal.module=ALL-UNNAMED \
--add-opens \
java.base/jdk.internal.ref=ALL-UNNAMED \
--add-opens \
java.base/jdk.internal.reflect=ALL-UNNAMED \
--add-opens \
java.base/java.io=ALL-UNNAMED \
--add-opens \
java.base/java.lang=ALL-UNNAMED \
--add-opens \
java.base/java.lang.reflect=ALL-UNNAMED \
--add-opens \
java.base/java.lang.invoke=ALL-UNNAMED \
--add-opens \
java.base/java.lang.ref=ALL-UNNAMED \
--add-opens \
java.base/java.net=ALL-UNNAMED \
--add-opens \
java.base/java.nio=ALL-UNNAMED \
--add-opens \
java.base/java.nio.file=ALL-UNNAMED \
--add-opens \
java.base/java.security=ALL-UNNAMED \
--add-opens \
java.base/javax.crypto=ALL-UNNAMED \
--add-opens \
java.base/java.util=ALL-UNNAMED \
--add-opens \
java.base/java.util.concurrent.atomic=ALL-UNNAMED \
--add-opens \
java.base/sun.security.x509=ALL-UNNAMED \
--add-opens \
java.base/jdk.internal.logger=ALL-UNNAMED \
--add-opens \
org.graalvm.sdk/org.graalvm.nativeimage.impl=ALL-UNNAMED \
--add-opens \
org.graalvm.sdk/org.graalvm.polyglot=ALL-UNNAMED \
--add-opens \
org.graalvm.truffle/com.oracle.truffle.polyglot=ALL-UNNAMED \
--add-opens \
org.graalvm.truffle/com.oracle.truffle.api.impl=ALL-UNNAMED \
-XX:+UseJVMCINativeLibrary \
-Xss10m \
-Xms1g \
-Xmx14g \
-Duser.country=US \
-Duser.language=en \
-Dorg.graalvm.version=19.3.0 \
-Dorg.graalvm.config=EE \
-Dcom.oracle.graalvm.isaot=true \
--module-path \
~/vm/graalvm-ee-java11-19.3.0/lib/truffle/truffle-api.jar \
-Djdk.internal.lambda.disableEagerInitialization=true \
-Djdk.internal.lambda.eagerlyInitialize=false \
-Djava.lang.invoke.InnerClassLambdaMetafactory.initializeLambdas=false \
-cp \
~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/svm-llvm.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/objectfile.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/graal-llvm.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/svm-enterprise-llvm.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/svm.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/svm-enterprise.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/javacpp-shadowed.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/pointsto.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/llvm-platform-specific-shadowed.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/llvm-wrapper-shadowed.jar \
com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus \
-watchpid \
31292 \
-imagecp \
~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/svm-llvm.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/objectfile.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/graal-llvm.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/svm-enterprise-llvm.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/svm.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/svm-enterprise.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/javacpp-shadowed.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/pointsto.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/llvm-platform-specific-shadowed.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/builder/llvm-wrapper-shadowed.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/library-support-enterprise.jar:~/vm/graalvm-ee-java11-19.3.0/lib/svm/library-support.jar:~/projects/github/gh-1885/micronaut-basic-app/build/libs/basic-app-0.1-all.jar \
-H:Path=~/projects/github/gh-1885/micronaut-basic-app \
-H:+StaticExecutable \
-H:FallbackThreshold=0 \
-H:ClassInitialization=io.netty.util.AbstractReferenceCounted:run_time \
-H:ClassInitialization=io.netty.buffer.PooledByteBufAllocator:run_time,io.netty.buffer.ByteBufAllocator:run_time,io.netty.buffer.ByteBufUtil:run_time,io.netty.buffer.AbstractReferenceCountedByteBuf:run_time \
-H:ReflectionConfigurationResources=META-INF/native-image/io.netty/transport/reflection-config.json \
-H:ClassInitialization=io.netty.handler.ssl.util.ThreadLocalInsecureRandom:run_time \
-H:ClassInitialization=io.netty:build_time \
-H:ClassInitialization=io.netty.handler.codec.http.HttpObjectEncoder:run_time,io.netty.handler.codec.http.websocketx.WebSocket00FrameEncoder:run_time \
-H:IncludeResources=META-INF/http/mime.types \
-H:+AllowIncompleteClasspath \
-H:EnableURLProtocols=http,https \
-H:ReflectionConfigurationResources=META-INF/native-image/io.micronaut/http/reflection-config.json \
-H:ClassInitialization=com.sun.jndi.dns.DnsClient:run_time,io.netty.handler.ssl.ConscryptAlpnSslEngine:run_time,io.netty.handler.ssl.JettyNpnSslEngine:run_time,io.netty.handler.ssl.ReferenceCountedOpenSslEngine:run_time,io.netty.handler.ssl.JdkNpnApplicationProtocolNegotiator:run_time,io.netty.handler.ssl.ReferenceCountedOpenSslServerContext:run_time,io.netty.handler.ssl.ReferenceCountedOpenSslClientContext:run_time,io.netty.handler.ssl.util.BouncyCastleSelfSignedCertGenerator:run_time,io.netty.handler.ssl.ReferenceCountedOpenSslContext:run_time,io.micronaut.buffer.netty.NettyByteBufferFactory:run_time \
-H:ReflectionConfigurationResources=META-INF/native-image/io.micronaut/http-netty-channel/reflection-config.json \
-H:ClassInitialization=io.micronaut.reactive.reactor.ReactorInstrumentation:run_time \
-H:ClassInitialization=ch.qos.logback:build_time,com.fasterxml.jackson:build_time,io.micronaut:build_time,io.reactivex:build_time,org.reactivestreams:build_time,org.slf4j:build_time,org.yaml.snakeyaml:build_time,javax:build_time \
-H:ReflectionConfigurationResources=META-INF/native-image/io.micronaut/health/reflection-config.json \
-H:IncludeResources=logback.xml|application.yml|bootstrap.yml \
-H:Name=basic-app \
-H:Class=example.micronaut.Application \
-H:ReflectionConfigurationResources=META-INF/native-image/example/micronaut/reflection-config.json \
-H:CLibraryPath=~/vm/graalvm-ee-java11-19.3.0/lib/svm/clibraries/linux-amd64
]
Awesome, thanks!
@ilopmar when can we see a new Micronaut release with the fix?
The PR (https://github.com/micronaut-projects/micronaut-core/pull/2418) has been merged so it will be included in the next release. At this moment it has been merged in 1.2.x branch but we will merge it into master so it is also included in 1.3.0.M2.
Adding this here for reference as a workaround until we release next Micronaut version:
Create the file src/main/graal/reflect.json with the content:
[
{
"name": "sun.nio.ch.SelectorImpl",
"fields": [
{"name": "selectedKeys", "allowUnsafeAccess": true},
{"name": "publicSelectedKeys", "allowUnsafeAccess": true}
]
}
]
Most helpful comment
The PR (https://github.com/micronaut-projects/micronaut-core/pull/2418) has been merged so it will be included in the next release. At this moment it has been merged in
1.2.xbranch but we will merge it intomasterso it is also included in 1.3.0.M2.