Native Image Committer and Community Meeting 2026-08-27 #14303
Unanswered
wirthi
asked this question in
Show and tell
Replies: 1 comment
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
List of all past and upcoming meetings: #3933
The meeting will be at our regular time of 17:00 CET: https://www.timeanddate.com/worldclock/fixedtime.html?iso=20260827T08&p1=224
The meeting after this one is planned for September 24th, 2026. The meeting will typically be on the last Thursday of each month.
PRs listed below were merged between July 28th and August 25th (roughly).
New and Noteworthy
https://www.graalvm.org/release-calendar/
Native Image Layers and Analysis improvements
Layers
(summarized change) Decodes executable annotations from their metadata layer.
(summarized change) Allows
VMLockingPrimitiveto be shared by extension layers.(summarized change) Defines a code-section symbol for application layers.
(summarized change) Adds the initial-layer core types needed for layered images.
Other Analysis improvements
(summarized change) Exposes hosted code-generation extension points.
Project Crema
Guards Crema runtime options, only check in Crema (
-H:+RuntimeClassLoading) mode and fold their code otherwise.Ristretto (Crema JIT compiler)
Project Terminus: Towards the "Hello, Espresso World!" #12236
(summarized change) Moves
KnownIntrinsicsand guest-facing compiler intrinsics required by the thread runtime into guest staging while keeping compiler implementation details builder-owned.(summarized change) Preserves
JavaConstantvalues throughout object-reachability callbacks, allowing guest callbacks to run without materializing arbitrary guest objects in the builder.(summarized change) Unwraps builder exceptions crossing guest invocations through host proxies while preserving the existing representation of genuine guest exceptions.
(summarized change) Introduces context-aware annotation access so builder-to-guest queries use JVMCI metadata while same-context queries use the appropriate builder or guest backend.
(summarized change) Generates typed wrappers over JVMCI
AnnotationValuemetadata and replaces manually maintained wrappers used by Native Image features and substitutions.(summarized change) Removes unnecessary builder-side annotation proxies by reading guest annotations directly as JVMCI metadata or generated typed wrappers.
(summarized change) Migrates Native Image substitution processing from builder reflection to JVMCI and guest-owned metadata.
(summarized change) Moves runtime metadata annotations, heap-access declarations, and stack-value intrinsic declarations into guest staging.
(summarized change) Removes the obsolete built-in Gson feature, eliminating a guest-only feature registration failure on the Terminus HelloWorld path.
Streamline reachability metadata
(summarized change) Improves reachability-metadata documentation and schema accessibility.
(summarized change) Adds a layered workflow for reachability metadata.
i.e. execute the reachability metadata tests in a layered setup
Usability
(summarized change) Adds Native Image tuning support.
-H:±PreserveIncludesJNI. #14208(summarized change) Introduces -H:±PreserveIncludesJNI.
(summarized change) Fixes Windows native-image command-file serialization.
(summarized change) Supports assignment syntax for native-image options.
(summarized change) Fixes Windows rebuild checks for native-image resource-file lists.
(summarized change) Adds an actionable out-of-space hint when writing the image file.
Monitoring / Tooling / Debugging
Garbage Collector / Memory Management
Other & fixes
i.e. better results with
readelfmore tests executed on Windows in general
Questions
Layered Native Image: faster builds and resource sharing
Layered Native Image splits a native executable into independently built layers. An application layer can reuse code and data from an initial shared layer, much like an executable uses a shared library.
This can make application builds faster, make application artifacts smaller, and reduce total memory and disk usage when several applications share the same base.
Build the substantial foundation once, then reuse it across smaller application artifacts.
How layered images work
Dependencies between image layers are strictly vertical. Every layer has a single dependency; unrelated layers cannot be combined horizontally after they have been built.
For example, several applications can share the same library and Java base layers:
%%{init: {"theme":"base","block":{"padding":24},"themeVariables":{"fontFamily":"-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif","fontSize":"18px","lineColor":"#64748b"}}}%% block columns 5 app1["app1"] app2["app2"] app3["app3"] app4["app4"] app5["app5"] space:5 lib1["lib1.so"]:2 lib2["lib2.so"] lib12["lib1-2.so"] space space:5 base["libjavabase.so"]:4 base1["libjavabase-1.so"] app1 --> lib1 app2 --> lib1 app3 --> lib2 app4 --> lib12 app5 --> base1 lib1 --> base lib2 --> base lib12 --> base classDef application fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#172554 classDef library fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#451a03 classDef baseLayer fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#450a0a class app1,app2,app3,app4,app5 application class lib1,lib2,lib12 library class base,base1 baseLayerThis means that a build cannot simply create one independent layer for every library and mix those layers as needed. It must either build a sequence of layers or create a larger shared layer containing several libraries.
Platform support and testing
Layered Native Image now supports all Native Image platforms:
Layer tests run against libraries in the GraalVM Reachability Metadata Repository. Two configurations are tested for each library:
The latest test results are:
The trade-offs
Moving code into a shared layer changes where build time, artifact size, and runtime costs occur.
The best split therefore depends on how frequently each layer changes and how many applications will share it.
Current results
The current measurements show the expected trade-off: creating the initial layer is expensive, while subsequent application layers are substantially faster and smaller. Resource sharing becomes more valuable as more applications use the same initial layer.
The following results are from the Micronaut Shopcart benchmark.
Note: The Efficiency and the First repsonse were not explored at all yet.
Try it out for yourself
Start with a
native-imagecommand that successfully builds a standalone application. Then split it into two builds. First, create a base-layer archive and select its contents withmodule,package, orpathentries:native-image \ -H:LayerCreate=base-layer.nil,module=java.base,package=io.micronaut.* \ -cp library.jarThen build the application with the same class path, module path, and relevant build options, adding the base layer as an input:
native-image \ -H:LayerUse=base-layer.nil \ -cp library.jar -cp . com.example.ApplicationDuring
LayerCreate, Native Image performs an open-world reachability analysis over the selected base-layer content. This discovers the base-layer universe—the types, methods, fields, constants, and other metadata that an application layer may later reference.The resulting
.nilarchive contains a snapshot of that universe and the available image singletons, serialized compiler graphs, the platform-native shared library, and properties describing the layer's inputs and configuration.LayerUsevalidates compatibility, imports this state into the application build, and extends the analysis with the application code. The final executable links against the shared library at run time.moduleincludes all classes and resources from a module, whilepackageselects individual packages.pathincludes an entire class-path entry and its resources, but may produce a larger layer than necessary.The layer and application builds must use compatible JDK, GraalVM, native toolchain, class-path entries, and build options. If a shared JAR changes, rebuild the base layer. Layer archives are also specific to the operating system and architecture. See the Layered Native Image documentation and GraalVM demos for complete examples.
To see the resource-sharing benefit, run several applications that use the same initial layer. Copying the same application executable is sufficient for this experiment. The Micronaut comparison example builds both layered and standalone executables, can create multiple copies of each application, and reports their combined resident set size (RSS), proportional set size (PSS), and unique set size (USS).
Reproducing VM state across builds
Every layer is produced by a separate build process, but later layers must refer back to state created by earlier processes. This is difficult when an element has an unstable name or when a value differs between builds.
Separate builds must agree on one consistent view of shared runtime and static state.
Examples include:
One of the major challenges in layered builds is keeping static state consistent across separate build processes. A static value created or initialized while building the initial layer must not be silently duplicated, replaced, or observed inconsistently when the application layer is built.
A state mismatch can produce failures that are difficult to diagnose. Open-world analysis can also make more code reachable and expose issues in that code that were never uncovered.
Shared layers additionally miss some optimizations that are possible when the whole application is known. In particular, the shared-layer build cannot devirtualize every call or over-optimize analysis states based on one application.
Diagnosing and fixing inconsistencies
LayeredImageOptionsprovides options for identifying state that does not reproduce consistently. For example:When static state depends on the application, it should be created in the application layer rather than captured in the initial layer. These options provide that mitigation:
ApplicationLayerInitializedClassesdelays build-time initialization of selected classes until the application-layer build, so their static fields are initialized with application-layer state.ApplicationLayerOnlySingletonskeeps selected image singletons out of the initial layer and installs them only in the application layer.Options must remain consistent across layers
Most Native Image options need the same value in every layer, although some options may change between layers.
This option verifies that the layers use compatible values. Not all Native Image options are currently handled, and runtime options cannot be set in a shared layer.
APIs for layer-aware features
Layer-aware APIs define how code and state cross layer boundaries. They specify which layer owns an image singleton, where a method is compiled, how a field installed in an earlier layer can be updated, and how code in one layer refers to a constant from another. Together, these APIs keep separately built layers consistent at run time.
Singleton traits
@SingletonTraitsdefines whether an image singleton is accessible at build time or run time, where it is installed, and whether it participates in layered callbacks. For example, this simplified excerpt fromPosixSignalHandlerSupportmakes the singleton available at build time and run time, but installs its runtime instance only in the initial layer:This is useful for process-wide state such as signal handling: code in later layers refers to the same runtime object instead of installing an incompatible duplicate.
@SingletonTraitstherefore provides an explicit solution to the broader state-consistency problem for image singletons. Other traits can make a singleton application-layer only, allow one instance per layer, or persist additional state between builds.Layered compilation behavior
@LayeredCompilationBehaviorcontrols where a method is compiled.VMInspectionOptionsdelays heap-dump path creation until the application layer:The base layer does not yet know the final application image name. Delaying this method prevents the base image name from being compiled into application behavior. A method can also be pinned to the initial layer when it must be part of the shared implementation.
Layered field values
@LayeredFieldValuelets a later layer update a field on an object installed by an earlier layer. InDynamicHubCompanion, an array class may become reachable only in a later layer:The transformer updates the existing companion to point to the newly installed array hub. This preserves object identity and avoids leaving the shared object with a stale
nullvalue.Cross-layer constants
CrossLayerConstantRegistrygives an object installed in one layer a stable name that later builds can resolve.SystemInOutErrFeatureuses it for the runtimeSystem.outobject:The hosted
System.outobjects belong to different JVM build processes, so Java object identity cannot connect them. The registry lets application-layer code refer to the exact runtime object already stored in the initial-layer heap.Build-tool DSL
The Native Build Tools provide built-in layer support for both Gradle and Maven. A build can declare layer contents directly in its configuration, resolve selected JARs and their transitive dependencies, and create or consume layers without manually assembling Native Image arguments.
Gradle can reuse an unchanged layer instead of rebuilding it. Named layers are declared and attached with
useLayer(…). Maven builds can create layers withlayer-createand consume them as Native Image layer dependencies.See native-build-tools pull request #1011 for more information.
Planned next steps
All reactions