RFR: 8329706: Implement -XX:+AOTClassLinking [v5]

Ashutosh Mehra asmehra at openjdk.org
Fri Sep 13 16:13:10 UTC 2024


On Thu, 12 Sep 2024 21:43:24 GMT, Ioi Lam <iklam at openjdk.org> wrote:

>> This is the 3rd PR for [JEP 483: Ahead-of-Time Class Loading & Linking](https://bugs.openjdk.org/browse/JDK-8315737).
>> 
>> **Overview**
>> 
>> - A new `-XX:+AOTClassLinking` flag is added. See [JEP 498](https://bugs.openjdk.org/browse/JDK-8315737) and the [CSR](https://bugs.openjdk.org/browse/JDK-8339506) for a discussion of this command-line option, its default value, and its impact on compatibility.
>> - When this flag is enabled during the creation of an AOT cache (aka CDS archive), an `AOTLinkedClassTable` is added to the cache to include all classes that are AOT-linked. For this PR, only classes for the boot/platform/application loaders are eligible. The main logic is in `aotClassLinker.cpp`.
>> - When an AOT archive is loaded in a production run, all classes in the `AOTLinkedClassTable` are loaded into their respective class loaders at the earliest opportunity. The main logic is in `aotLinkedClassBulkLoader.cpp`.
>>   - The boot classes are loaded as part of `vmClasses::resolve_all()`
>>   - The platform/application classes are loaded after the module graph is restored (see changes in `threads.cpp`).
>> - Since all classes in a `AOTLinkedClassTable` are loaded before any user-code is executed, we can resolve constant pool entries that refer to these classes during AOT cache creation. See changes in `AOTConstantPoolResolver::is_class_resolution_deterministic()`.
>> 
>> **All-or-nothing Loading**
>> 
>> - Because AOT-linked classes can refer to each other, using direct C++ pointers, all AOT-linked classes must be loaded together. Otherwise we will have dangling C++ pointers in the class metadata structures. 
>> - During a production run, we check during VM start-up for incompatible VM options that would prevent some of the AOT-linked classes from being loaded. For example:
>>   - If the VM is started with an JVMTI agent that has ClassFileLoadHook capabilities, it could replace some of the AOT-linked classes with alternative versions.
>>   - If the VM is started with certain module options, such as `--patch-module` or `--module`, some AOT-linked classes may be replaced with patched versions, or may become invisible and cannot be loaded into the JVM.
>> - When incompatible VM options are detected, the JVM will refuse to load an AOT cache that has AOT-linked classes. See `FileMapInfo::validate_aot_class_linking()`.
>>   - For simplfication, `FileMapInfo::validate_aot_class_linking()` requires `CDSConfig::is_using_full_module_graph()` to be true. This means that the exa...
>
> Ioi Lam has updated the pull request incrementally with one additional commit since the last revision:
> 
>   @ashu-mehra comments

src/hotspot/share/cds/aotClassLinker.cpp line 227:

> 225: }
> 226: 
> 227: int AOTClassLinker::num_initiated_classes(oop loader1, oop loader2) {

The two loader arguments here are quite confusing marking it hard to understand the code. Can it be refactored as this:


int AOTClassLinker::num_platform_initiated_classes() {
  // AOTLinkedClassBulkLoader will initiate loading of all public boot classes in the platform loader.
  return num_initiated_classes(nullptr);
}

int AOTClassLinker::num_app_initiated_classes() {
  // AOTLinkedClassBulkLoader will initiate loading of all public boot/platform classes in the app loader.
  return num_platform_initiated_classes + num_initiated_classes(SystemDictionary::java_platform_loader());
}

int AOTClassLinker::num_initiated_classes(oop loader) {
  int n = 0;
  for (int i = 0; i < _sorted_candidates->length(); i++) {
    InstanceKlass* ik = _sorted_candidates->at(i);
    if (ik->is_public() && !ik->is_hidden() &&
        (ik->class_loader() == loader) {
      n++;
    }
  }

  return n;
}

src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp line 199:

> 197:     InstanceKlass* ik = classes->at(i);
> 198:     assert(ik->is_loaded(), "must have already been loaded by a parent loader");
> 199:     assert(ik->class_loader() != initiating_loader(), "must be a parent loader");

Can we also add an assert that ik->class_loader() must be either boot or platform loader.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/20843#discussion_r1759128918
PR Review Comment: https://git.openjdk.org/jdk/pull/20843#discussion_r1759129552


More information about the serviceability-dev mailing list