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 
jansidependency (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-clientdependency fromtesttocompilescope - 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/ValidationExceptionso 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.