63 lines
4.4 KiB
Plaintext
63 lines
4.4 KiB
Plaintext
Micronaut native-image build: the three failed attempts before the fix, verbatim
|
|
error text from the real `native-image` invocations (trimmed to the diagnostic
|
|
message; the full stack scan is in each build's svm_err_*.md, not committed since
|
|
it also repeats the full classpath).
|
|
|
|
=== Attempt 1 (no --initialize-at-build-time / --initialize-at-run-time args at all) ===
|
|
Failed generating 'micronaut-app' after 42.4s.
|
|
|
|
> com.oracle.graal.pointsto.util.ParallelExecutionException: An object of type 'ch.qos.logback.classic.Logger' was 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.
|
|
This is not allowed for correctness reasons: All objects that are stored in the image heap must be initialized at build time.
|
|
...
|
|
Object was reached by
|
|
scanning root constant ch.qos.logback.classic.Logger@7f585330: Logger[io.netty.util.ResourceLeakDetector] embedded in
|
|
<unknown>
|
|
at io.netty.util.ResourceLeakDetector.needReport() [bci: -5]
|
|
|
|
=== Attempt 2 (--initialize-at-build-time=ch.qos.logback.classic.Logger) ===
|
|
Failed generating 'micronaut-app' after 46.0s.
|
|
|
|
> com.oracle.graal.pointsto.util.ParallelExecutionException: An object of type 'ch.qos.logback.classic.LoggerContext' was found in the image heap. This type, however, is marked for initialization at image run time ...
|
|
Object was reached by
|
|
reading field ch.qos.logback.classic.Logger.loggerContext of constant
|
|
ch.qos.logback.classic.Logger@6f5cb3e9: Logger[io.netty.util.ResourceLeakDetector]
|
|
scanning root constant ch.qos.logback.classic.Logger@6f5cb3e9: Logger[io.netty.util.ResourceLeakDetector] embedded in
|
|
<unknown>
|
|
at io.netty.util.ResourceLeakDetector.needReport() [bci: -5]
|
|
|
|
=== Attempt 3 (--initialize-at-build-time=ch.qos.logback [whole package]) ===
|
|
Failed generating 'micronaut-app' after 49.9s.
|
|
|
|
> com.oracle.graal.pointsto.util.ParallelExecutionException: An object of type 'ch.qos.logback.classic.Logger' was found in the image heap. This type, however, is marked for initialization at image run time ...
|
|
(identical trace to Attempt 1 - the package-level directive lost to a more specific
|
|
--initialize-at-run-time directive for this exact class shipped in logback-classic's
|
|
own META-INF/native-image/*/native-image.properties: GraalVM lets a more specific
|
|
per-class directive override a broader package-level one, in either direction.)
|
|
|
|
=== Attempt 4 (--initialize-at-run-time=io.netty.util.ResourceLeakDetector,io.netty.util.ResourceLeakDetectorFactory) ===
|
|
Failed generating 'micronaut-app' after 42.9s.
|
|
|
|
> com.oracle.graal.pointsto.util.ParallelExecutionException: An object of type 'io.netty.util.ResourceLeakDetector' was found in the image heap. This type, however, is marked for initialization at image run time ...
|
|
Object was reached by
|
|
scanning root constant io.netty.util.ResourceLeakDetector@2a2de2c0: io.netty.util.ResourceLeakDetector@2a2de2c0 embedded in
|
|
io.netty.buffer.AbstractByteBufAllocator.toLeakAwareBuffer(AbstractByteBufAllocator.java:53)
|
|
parsing method io.netty.buffer.AbstractByteBufAllocator.toLeakAwareBuffer(AbstractByteBufAllocator.java:53) reachable via the parsing context
|
|
at static root method.(Unknown Source)
|
|
(deferring just the leak detector to run-time wasn't enough: AbstractByteBufAllocator,
|
|
itself build-time-initialized by default, holds a static reference to one.)
|
|
|
|
=== Fix that worked (--initialize-at-run-time=io.netty [whole package]) ===
|
|
Finished generating 'micronaut-app' in 7m 15s.
|
|
2,621 types -> 3,395 types reachable after the fix (more code stays reachable because
|
|
initialization now genuinely happens at run time instead of being folded away), image
|
|
heap 854MB peak RSS during the build, final executable 53.31MiB.
|
|
|
|
Takeaway for the post: this is a build-time ordering conflict between two framework
|
|
defaults, not a bug in either library - Netty wants its leak detector and buffer
|
|
allocator built eagerly (for speed), logback wants its Logger/LoggerContext run-time
|
|
(so file handles and config aren't baked into the image), and the two defaults only
|
|
collide when both are on the classpath AND something (here, static root scanning
|
|
during Micronaut's own analysis) forces Netty's allocator to be build-time reachable.
|
|
Pushing the whole io.netty package to run-time init was the fix that actually stuck;
|
|
chasing individual classes one GraalVM error message at a time was not.
|