micronaut-core: Unable to create native image with micronaut-http-client and jansi
I’m trying to build an interactive shell application with Micronaut and Jansi but i’m unable to compile it as a GraalVM native image. The compilation fails when both the jansi
and micronaut-http-client
dependency are on the classpath. The jansi
dependency doesn’t contain any links to the project which contains the class in the exception (netty-tcnative, io.netty.internal.tcnative.SSLPrivateKeyMethod) as far as I know but does use JNI which might trigger the error in Micronaut or Netty.
@ilopmar do you have any idea what could cause this error or how to make GraalVM show which class refers to to the mentioned class?
Task List
- Steps to reproduce provided
- Stacktrace (if present) provided
- Example that reproduces the problem uploaded to Github
- Full description of the issue provided (see below)
Steps to Reproduce
- Create a new Micronaut CLI app (
mn create-cli-app --build=maven --lang=java --test=junit --features=graalvm,jib,logback,mockito,shade my.package.app
) - Build native image (
./mvnw clean package -Dpackaging=docker-native -Pgraalvm
) - Add
jansi
dependency (org.fusesource.jansi:jansi:2.3.2
, https://github.com/fusesource/jansi/) - Build native image (
./mvnw clean package -Dpackaging=docker-native -Pgraalvm
) - Change
micronaut-http-client
dependency fromtest
tocompile
scope - Building native image will fail (
./mvnw clean package -Dpackaging=docker-native -Pgraalvm
)
Expected Behaviour
The GraalVM native image compiler should succeed in creating a native image. This is the case when one of the micronaut-http-client
or jansi
dependencies are removed.
Actual Behaviour
The GraalVM native image compiler fails with an exception:
Fatal error:java.lang.NoClassDefFoundError
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:499)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:370)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:531)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:119)
at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:568)
Caused by: java.lang.NoClassDefFoundError: io/netty/internal/tcnative/SSLPrivateKeyMethod
at jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVM.getDeclaredMethods(Native Method)
at jdk.internal.vm.ci/jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.getDeclaredMethods(HotSpotResolvedObjectTypeImpl.java:987)
at com.oracle.svm.jni.access.JNIAccessibleMethod.anyMatchIgnoreReturnType(JNIAccessibleMethod.java:139)
at com.oracle.svm.jni.access.JNIAccessibleMember.findHidingSubclasses(JNIAccessibleMember.java:103)
at com.oracle.svm.jni.access.JNIAccessibleMember.findHidingSubclasses(JNIAccessibleMember.java:110)
at com.oracle.svm.jni.access.JNIAccessibleMember.setHidingSubclasses(JNIAccessibleMember.java:83)
at com.oracle.svm.jni.access.JNIAccessibleMethod.finishBeforeCompilation(JNIAccessibleMethod.java:135)
at com.oracle.svm.jni.access.JNIAccessFeature.beforeCompilation(JNIAccessFeature.java:363)
at com.oracle.svm.hosted.NativeImageGenerator.lambda$doRun$8(NativeImageGenerator.java:644)
at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:71)
at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:644)
at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$2(NativeImageGenerator.java:495)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1407)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.ClassNotFoundException: io.netty.internal.tcnative.SSLPrivateKeyMethod
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 18 more
Environment Information
- Operating System: MacOS Catalina / Docker Desktop 3.3.1
- Micronaut Version: 2.4.2
- JDK Version: GraalVM Java 11 21.0.0.2 (same for 21.1.0)
Example Application
Example application is simply created with steps to reproduce the issue.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 17 (17 by maintainers)
@traycho The GraalVM team fixed the issue and it will be included in GraalVM 21.2 (to be released on July 20th). I tried with my application and it works properly. Another thing fixed is that now the substitutions are not needed anymore.
@traycho you have a workaround here: https://github.com/micronaut-projects/micronaut-core/issues/5328#issuecomment-829912994 but we are waiting on GraalVM issue https://github.com/oracle/graal/issues/3387
I’ve just tried those SSL substitutions in the sample app used in the GraalVM issue and it works!
I’ve also tried with a new Micronaut 2.4.4 application adding the jansi dependency and with the same substitutions, it works. There is an error with class
org/grails/datastore/mapping/validation/ValidationException
so I tried using a locally built Micronaut snapshot without that class and, as mentioned it works.P.S: I’ve tried with a normal Micronaut app and used Gradle, but I think that won’t make any difference.