Open erkieh opened 8 months ago
Hey @erkieh,
I am not a Micronaut project contributor, but I can probably still help you out with this. GraalVM performs class initialization at either build time or run time. Which classes are loaded and in what order depends on each application, of course, so these errors vary quite a bit and may surface in Launch-generated samples.
It is frequent to run into these errors when building a native app with GraalVM, and it isn't always immediately clear what to do, but there are some ways to figure it out. Here are the steps I take, which nearly always work eventually:
1) Mark the class as --initialize-at-build-time
If you pass --initialize-at-build-time=<class>
during the build, to native-image
, you are telling the Native Image builder that the subject class is OK to initialize at build time, and this alone will often clear up the error, so long as the class is sensible to initialize at build time in the first place, which isn't always true. In that case, you can...
2) Mark the class as --initialize-at-run-time
If you pass --initialize-at-run-time<class>
, native-image
will try to defer initialization for that class and any related necessary classes. For example, say you have a class which uses epoll
on Linux; epoll may not always be available, and you may want to fall back to NIO. You could initialize such a class at runtime to avoid the build-time environment from governing whether support is detected.
3) Run with --trace-object-instantiation
When you're not sure which of the above to use for a given class, you can use --trace-object-instantiation=<class>
, which will print more information about why the class in question was instantiated at build time.
What I see from your log is that several Logback classes are showing up as initialized at build time, which makes sense: logback.xml
is loaded early in the program lifecycle. There are some Netty classes too. If you have trouble figuring out the right flags to use, I can try to dig up one of the cases where we also encountered these and see what flags made it work.
Hi @sgammon Thanks for replying. I did try creating a reflect-config.json in a real project with the help of trace flags, but it felt like a rabbit hole with no bottom. It would be interesting to see what got it working in your case.
This has to be fixed upstream in native image.
I've created an internal tracking ticket (GR-54365) for this.
Expected Behavior
Tests succeed
Actual Behaviour
Errors are thrown about objects "found in the image heap. This type, however, is marked for initialization at image run time for the following reason: classes are initialized at run time by default"
I have attached logs with Kotest and Junit.
logs.txt
Steps To Reproduce
curl --location --request GET 'https://launch.micronaut.io/create/default/com.example.demo?lang=KOTLIN&build=GRADLE_KOTLIN&test=KOTEST&javaVersion=JDK_21' --output demo.zip
gradle nativeTest
Environment Information
Windows 10 and GraalVM for JDK 21
Example Application
curl --location --request GET 'https://launch.micronaut.io/create/default/com.example.demo?lang=KOTLIN&build=GRADLE_KOTLIN&test=KOTEST&javaVersion=JDK_21' --output demo.zip
Version
4.3.7