On Fri, 23 Oct 2026 03:22:23 GMT, Ioi Lam <[email protected]> wrote:
>> Before this PR, you cannot use -XX:AOTCache in the training run:
>>
>>
>> $ java -XX:AOTCache=foo.aot -cp HelloWorld.jar \
>> -XX:AOTMode=record -XX:AOTConfiguration=hw.aotconfig \
>> HelloWorld
>> [...] AOTCache must not be specified when using -XX:AOTMode=record
>>
>>
>> However, in some cases, it may be desirable to train the AOT cache in two or
>> more steps. For example:
>>
>> ## Separate Training for Framework and Application:
>>
>> - First perform a training run to exercise commonly-used areas of the
>> framework.
>> - Second, perform a training run of a specific application.
>>
>> The idea is that important parts of the framework may not be covered by a
>> single application training run, but they may still be used in the
>> production run due to runtime-specific input.
>>
>>
>> # Train the framework
>> java -XX:AOTCacheOutput=first.aot -cp FrameWork.jar FrameWorkTraningHelper
>>
>> # Train the app
>> java -XX:AOTCache=first.aot -XX:AOTCacheOutput=second.aot -cp
>> FrameWork.jar:App.jar MyApp
>>
>> # Production run using second.aot, which contains artifacts from
>> # the first and second training runs
>> java -XX:AOTCache=second.aot -cp FrameWork.jar:App.jar MyApp
>>
>> Note that the classpaths of the training runs must be compatible. I.e., the
>> classpath of an earlier training run must be the same as, or the prefix of,
>> the classpath of a later training run.
>>
>> ## Train the Same Application in Multiple Runs:
>>
>> An application may perform 3 different operations. It's not easy to perform
>> all 3 operations in a single training run, as the 3 operations are
>> represented by 3 separate main classes (`WalkDog`, `FeedCat`, and
>> `WaterPlants`). So, we perform 3 separate training runs and combine the
>> results into a single AOT cache.
>>
>>
>> # Training
>> java -XX:AOTCacheOutput=tmp1.aot -cp MyApp.jar WalkDog
>> java -XX:AOTCache=tmp1.aot -XX:AOTCacheOutput=tmp2.aot -cp MyApp.jar FeedCat
>> java -XX:AOTCache=tmp2.aot -XX:AOTCacheOutput=final.aot -cp MyApp.jar
>> WaterPlants
>>
>> # Production: final.aot contains artifacts for optimizing all 3 operations:
>> java -XX:AOTCache=final.aot -cp MyApp.jar WalkDog
>> java -XX:AOTCache=final.aot -cp MyApp.jar FeedCat
>> java -XX:AOTCache=final.aot -cp MyApp.jar WaterPlants
>>
>>
>> ---------
>> - [x] I confirm that I make this contribution in accordance with the
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> Ioi Lam has updated the pull request with a new target base due to a merge or
> a rebase. The pull request now contains 55 commits:
>
> - cleaned up comment
> - Merge branch 'master' into aot-re-training
> - @vnkozlov comments -- check AOTReplayTraining
> - @vnkozlov comment -- removed unnecessary code
> - Renamed the CDSAppTester workflows to AOT-Iterative1 and AOT-Iterative2
> - updated man page
> - Merge branch 'master' into aot-re-training
> - Avoid crashing inside ciRecords::Arguments<>::prepare() because
> _first==nullptr
> - Merge branch 'master' into aot-re-training
> - Fixed bug found in AOT/JCK testing
> - ... and 45 more: https://git.openjdk.org/jdk/compare/722e2fff...df2dd3ef
src/hotspot/share/cds/archiveBuilder.cpp line 646:
> 644: memcpy(dest, src, bytes);
> 645: if (CDSConfig::is_redumping_aot_configuration() && src_info->type() ==
> MetaspaceClosureType::ClassType) {
> 646: // This class was aot-initialized in the input AOT cache, but we
> never aot-initialize classes in the
Not every class is aot-initialized, but the comment and the check implies all
classes are aot-initialized and that when redumping the flag has to be cleared.
src/hotspot/share/cds/archiveUtils.hpp line 221:
> 219: };
> 220:
> 221: // RAII helper for demarcating data structures that are loaded from the
> input archive in
This looks more of a general purpose mechanism for disabling writing of certain
data structures, irrespective of which archive is being written. Just that it
is currently only used when redumping the config file. Perhaps the comment can
be tweaked a bit on these lines.
src/hotspot/share/cds/cdsConfig.cpp line 790:
> 788: assert(new_aot_flags_used(), "");
> 789:
> 790: if (is_dumping_preimage_static_archive()) {
Would it be better to use the new API `is_dumping_aot_configuration()`?
src/hotspot/share/cds/cdsConfig.cpp line 809:
> 807: }
> 808: disable_dumping_aot_code(); // No AOT code generation during
> training run
> 809: } else if (is_dumping_final_static_archive()) {
Same as above, should it be using new API `is_dumping_aot_cache()`?
src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp line 65:
> 63: }
> 64:
> 65: if (exclude_reason != nullptr &&
> !!SystemDictionaryShared::is_excluded_class(k)) {
extra `!`
src/hotspot/share/cds/filemap.cpp line 233:
> 231: FileMapInfo* FileMapInfo::allocate_dynamic_input_archive(const char*
> filename) {
> 232: precond(_dynamic_input_archive == nullptr);
> 233: _dynamic_input_archive = new FileMapInfo(filename,
> /*is_dynamic=*/false);
Comment should be `is_static=`
src/hotspot/share/runtime/sharedRuntime.cpp line 3453:
> 3451:
> 3452: void
> AdapterHandlerLibrary::serialize_shared_table_header(SerializeClosure* soc) {
> 3453: // This table is used for loading cached adapters in a retaining
> JVM. However,
typo: retaining -> retraining
there is also 2 spaces between "adapters" and "in".
src/hotspot/share/runtime/sharedRuntime.cpp line 3458:
> 3456: AOTWriteClosureDisabler
> disable_if(CDSConfig::is_redumping_aot_configuration());
> 3457:
> 3458: _aot_adapter_handler_table.serialize_header(soc);
`serialize_header` writes a couple of ints and pointers. Pointers are taken
care of (null-ed out) when `AOTWriteClosureDisabler` is active but the ints are
not zeroed out. This can cause inconsistency in the archived header data.
src/java.base/share/man/java.md line 4186:
> 4184: The `-XX:AOTCache=<oldcache>` option is allowed when a JVM process
> is executed with the AOTMode
> 4185: of `record` (i.e., this JVM process is executing an AOT training
> run). If this option is specified,
> 4186: `<oldcache>` must be a valid AOT cache. The AOT configuration file
> written by this JVM process will
This given an impression that only the profile data from the old cache is used.
But there can also be linked classes from the old cache which may not otherwise
be loaded in this training run.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396319916
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396321720
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396322831
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396323037
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396323784
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396314647
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396330353
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396332308
PR Review Comment: https://git.openjdk.org/jdk/pull/31344#discussion_r4396335201