RFR: 8365932: Implementation of JEP 516: Ahead-of-Time Object Caching with Any GC [v3]
Serguei Spitsyn
sspitsyn at openjdk.org
Fri Oct 17 09:28:05 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
src/hotspot/share/prims/jvmtiExport.cpp line 1476:
> 1474: // virtual threads. When exiting it is filtered out due to being hidden.
> 1475: return;
> 1476: }
This has to be okay for now.
It can be done in more generic way. For instance, there is a check for `thread->is_hidden_from_external_view()` below which would be nice to have earlier. However, now there is an inconsistency with the flag `is_hidden_from_external_view()` usage we need to address in the near future. So, I'm suggesting to keep this tweak as it is now.
Most likely, we need to make sure other JVMTI events are not posted for this thread as well. I can file a separate JVMTI bug on it if it is okay with you.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/27732#discussion_r2439002671
More information about the build-dev
mailing list