APIdia Launch Partner
Top Description Methods
jdk.internal.vm.annotation

public @Interface AOTSafeClassInitializer

extends Annotation
Annotations
@Retention:RUNTIME
@Target:TYPE
Imports
java.lang.annotation.ElementType, .Retention, .RetentionPolicy, .Target

Indicates that the annotated class or interface is allowed to be AOT-initialized, because its author considers it safe to execute the static initializer of the class or interface during the AOT assembly phase.

For a class or interface X annotated with @AOTSafeClassInitializer, it will be initialized in the AOT assembly phase under two circumstances:

  1. If X was initialized during the AOT training run, the JVM will proactively initialize X in the assembly phase.
  2. If X was not initialized during the AOT training run, the initialization of X can still be triggered by normal execution of Java code in the assembly phase. At present this is usually the result of performing AOT optimizations for the java.lang.invoke package but it may include other cases as well.

If X is initialized during the AOT assembly phase, the VM will store the values of the static fields of X in the AOT cache. Consequently, during the production run that uses this AOT cache, the static initializer (<clinit>) of X will not be executed. X will appear to be in the "initialized" state and all the cached values of the static field of X will be available immediately upon the start of the prodcution run.

Currently, this annotation is used mainly for two purposes:

In more detail, the AOT assembly phase performs the following:

  1. It loads and links (but does not initialize) the classes that were loaded during the application's training run.
  2. During linking of these classes, it resolves their constant pool entries, when it is safe and beneficial to do so.
  3. As part of those resolutions, bootstrap methods may be called and may create graphs of Java objects to support linkage states.
  4. Every object within those graphs must have its class AOT-initialized, along with every relevant superclass and implemented interface, along with classes for every object created during the course of static initialization (running <clinit> for each such class or interface).
  5. In addition, any class/interface annotated with @AOTSafeClassInitializer that was initialized during the training run is proactively initialized.

Thus, in order to determine that a class or interface X is safe to AOT-initialize requires evaluating every other class or interface Y that the <clinit> of X will initialize (during AOT cache assembly), and ensuring that each such Y is (recursively) safe to AOT-initialize.

For example, an AOT-resolved constant pool entry for an invokedynamic or invokehandle bytecode can have direct or indirect references to Java objects. To ensure the correctness of the AOT-resolved constant pool entrties, the VM must AOT-initialize the classes of such Java objects.

In addition, such Java objects may have references to static fields whose object identity is important. For example, PrimitiveClassDescImpl::CD_void. To ensure correctness, we must also store classes like PrimitiveClassDescImpl in the initialized state. The VM requires implementor to manually annotate such classes with @AOTSafeClassInitializer.

There is one more requirement for a class to be safe for AOT initialization, and that is compatibility with all eventual production runs. The state of an AOT-initialized class X must not contain any data (anything reachable from X) that is incompatible with the eventual production run.

In general, if some sort of computed datum, environmental setting, or variable behavior may differ between the AOT assembly phase and the production run, it may not be immutably bound to X, if X is to be marked AOT-initialized. Here are specific examples:

What is more, if the initialization of X computes with some value V obtained from some other class Y, Y should also be safe for AOT initialization, if there is any way for X to detect a mismatch between the version of V produced at AOT time, and the version of V produced in the production run. Specifically, if V has an object identity, X should not test that identity (compare it against another or get its hashcode) unless Y is also marked for AOT initialization.

Thus, to support AOT-time linkage, a class X should be marked for (possible) AOT initialization whenever objects it creates (such as MethodHandles) may be required to execute a java.lang.invoke API request, or (more remotely) if the execution of such an API touches X for initialization, or even if such an API request is in any way sensitive to values stored in the fields of X, even if the sensitivity is a simple reference identity test.

The author of an AOT-initialized class may elect to patch some states at production startup, using an AOTRuntimeSetup method, as long as the pre-patched field values (present during AOT assembly) are determined to be compatible with the post-patched values that apply to the production run.

Before adding this annotation to a class X, the author must determine that it's safe to execute the static initializer of X during the AOT assembly phase. In addition, all supertypes of X must also have this annotation. If a supertype of X is found to be missing this annotation, the AOT assembly phase will fail.

This annotation is only recognized on privileged code and is ignored elsewhere.

Since
26

Method Summary

Inherited from java.lang.annotation.Annotation:
annotationTypeequalshashCodetoString