Files
framework-benchmarks/docs/output/06-micronaut-native-build-failures.txt

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.