RFR: 8365932: Implementation of JEP 516: Ahead-of-Time Object Caching with Any GC [v3]

Ioi Lam iklam at openjdk.org
Thu Oct 16 01:36:08 UTC 2025


On Wed, 15 Oct 2025 15:20:27 GMT, Erik Österlund <eosterlund at openjdk.org> wrote:

>> This is the implementation of JEP 516: Ahead-of-Time Object Caching with Any GC.
>> 
>> The current mechanism for the AOT cache to cache heap objects is by using mmap to place bytes from a file directly in the GC managed heap. This mechanism poses compatibility challenges that all GCs have to have bit by bit identical object and reference formats, as the layout decisions are offline. This has so far meant that AOT cache optimizations requiring heap objects are not available when using ZGC. This work ensures that all GCs, including ZGC, are able to use the more advanced AOT cache functionality going forward.
>> 
>> This JEP introduces a new mechanism for archiving a primordial heap, without such compatibility problems. It embraces online layouts and allocates objects one by one, linking them using the Access API, like normal objects. This way, archived objects quack like any other object to the GC, and the GC implementations are decoupled from the archiving mechanism.
>> 
>> The key to doing this GC agnostic object loading is to represent object references between objects as object indices (e.g. 1, 2, 3) instead of raw pointers that we hope all GCs will recognise the same. These object indices become the key way of identifying objects. One table maps object indices to archived objects, and another table maps object indices to heap objects that have been allocated at runtime. This allows online linking of the materialized heap objects.
>> 
>> The main interface to the cached heap is roots. Different components can register object roots at dump time. Each root gets assigned a root index. At runtime, requests can be made to get a reference to an object at a root index. The new implementation uses lazy materialization and concurrency. When a thread asks for a root object, it must ensure that the given root object and its transitively reachable objects are reachable. A new background thread called the AOTThread, tries to perform the bulk of the work, so that the startup impact of processing the objects one by one is not impacting the bootstrapping thread.
>> 
>> Since the background thread performs the bulk of the work, the archived is laid out to ensure it can run as fast as possible.
>> Objects are laid out inf DFS pre order over the roots in the archive, such that the object indices and the DFS traversal orders are the same. This way, the DFS traversal that the background thread is performing is the same order as linearly materializing the objects one by one in the or...
>
> Erik Österlund has updated the pull request incrementally with four additional commits since the last revision:
> 
>  - Dont print error message when there are no archived objects
>  - Fix issue in new test
>  - Change is_aot_thread implementation
>  - update AotJdk problem lists

Hi Eric, looks very good overall.

I have gone through some of the code and have some comments. More to come.

src/hotspot/share/cds/cds_globals.hpp line 79:

> 77:           "the CDS archive, in the specified file")                         \
> 78:                                                                             \
> 79:   product(bool, AOTStreamableObjects, true,                                 \

The default should be `false`, as that will be the mode that the user will get with no GC options are specified.

src/hotspot/share/cds/heapShared.cpp line 355:

> 353: }
> 354: 
> 355: bool HeapShared::is_loading_mapping_mode() {

I think `is_loading_mapping_mode()` should be removed and we should use only `is_loading_streaming_mode()`. This will make it easy to find all the places that checks between mapping/streaming. Same for `is_writing_xxx_mode()`.

Also, instead of having a tri-state of `_heap_load_mode`, it's better to have two boolean states:

- _is_loading_heap
- _is_loading_heap_streaming_mode

The first boolean is the main switch, but most of the code will be checking only the second boolean.

src/hotspot/share/cds/heapShared.cpp line 410:

> 408:       FLAG_SET_ERGO(AOTStreamableObjects, true);
> 409:       _heap_write_mode = HeapArchiveMode::_streaming;
> 410:       return;

This should be changed to `if (!UseZGC) {`, as all other GCs support writing the "mapping" format.

src/hotspot/share/cds/heapShared.cpp line 418:

> 416: 
> 417:   // Select default mode
> 418:   if (UseG1GC && UseCompressedOops) {

This is different than specified in JEP 516. The condition should be `if (UseCompressedOops)`.

test/hotspot/jtreg/runtime/cds/appcds/TestSerialGCWithCDS.java line 117:

> 115:                               small2,
> 116:                               coops,
> 117:                               "-XX:-AOTStreamableObjects",

Is this change necessary?

test/hotspot/jtreg/runtime/cds/appcds/TestSerialGCWithCDS.java line 147:

> 145:             // Regardless of which GC dumped the heap, there will be an object archive, either
> 146:             // created with mapping if dumped with G1, or streaming if dumped with serial GC.
> 147:             // At exec time, try to load them into a small SerialGC heap that may be too small.

Actually the original check of `dumpWithSerial == false` was obsolete, as SerialGC can also dump heap objects.  `dumpWithSerial == false` should be removed. The first two lines of comments should also be removed.

-------------

PR Review: https://git.openjdk.org/jdk/pull/27732#pullrequestreview-3342741298
PR Review Comment: https://git.openjdk.org/jdk/pull/27732#discussion_r2434315273
PR Review Comment: https://git.openjdk.org/jdk/pull/27732#discussion_r2434294269
PR Review Comment: https://git.openjdk.org/jdk/pull/27732#discussion_r2434328432
PR Review Comment: https://git.openjdk.org/jdk/pull/27732#discussion_r2434316323
PR Review Comment: https://git.openjdk.org/jdk/pull/27732#discussion_r2434295055
PR Review Comment: https://git.openjdk.org/jdk/pull/27732#discussion_r2434331254


More information about the build-dev mailing list