Summary
-------
Set class state to 'linked' when an archived boot class (loaded by the NULL class loader) is restored at runtime.
Problem
-------
The Java Virtual Machine Specification [1] ��5.4 states: ���Linking a class or interface involves verifying and preparing that class or interface, its direct superclass, its direct superinterfaces, and its element type (if it is an array type), if necessary���.
��5.5 states: ���Prior to initialization, a class or interface must be linked, that is, verified, prepared, and optionally resolved.��� [1] ��5.5
At archive dumping time, the VM loads boot classes using the NULL loader. The loaded classes are fully linked at dump time. The class states are reset to ���allocated��� before writing into the archive file (.jsa). After an archived boot class is loaded at runtime, it needs to go through normal class linking process again like any other dynamically loaded classes. Avoiding that duplicated work can improve runtime CPU utilization.
The Java Class Pre-resolution and Pre-initialization [2] proposal (proposed for the project Leyden) seeks a JVM spec compliant solution for selective class pre-initialization. The proposal also seeks an optimal approach with the least CPU and memory overhead. In order to achieve that, an archived boot class needs to be placed in 'linked' state early.
Solution
--------
When linking a class, the VM first links the super types (all super classes and super interfaces) of the current class. It then verifies and rewrites the bytecode for the current class, checks loader constraints, links methods, initializes the itable and vtable, and sets the current class to 'linked' state.
As described in above section, an archived boot class is fully linked (all linking work described above is done) at CDS dump time and the class state is reset to 'allocated' before the archive file is written. When loading an archived class at runtime, the VM makes sure all the super types in the class hierarchy for the current class are loaded first. If not, the archived class is not used and the VM then dynamically loads the requested class from the JAR file. That ensures the runtime class hierarchy is the same as dump time for any loaded archived boot class. Therefore, the class linking results achieved at CDS dump time remain valid at runtime.
An archived class is restored when it is 'loaded' at runtime. At the end of the restoration, all methods are linked and no other additional linking work is necessary for an archived boot class. The class is effectively in 'linked' state from that point. As a result, the VM can safely set the class state to 'linked' at the end of restoration. That avoids the work for re-iterating the super types in the class hierarchy.
Setting an archived class in 'linked' state during restoration enables the class to be placed in 'fully_initialized' state early for future optimizations.
During the normal class linking process, the VM posts ClassPrepare event for any JVMTI agent who registers the related callback. For an archived boot class, the VM is changed to post the ClassPrepare event immediately after the class is restored and set to 'linked' state. That does not affect dynamically loaded classes. The VM continues to post the ClassPrepare events for dynamically loaded classes at normal linking time, which usually happens as part of the class initialization.
JVM spec [1] ��5.4 allows eager or lazy linking (please see below). JVMTI agents should not rely on the exact timing or order of linking related events, particular the ClassPrepare event in this case.
"This specification allows an implementation flexibility as to when linking activities (and, because of recursion, loading) take place, provided that all of the following properties are maintained:
��� A class or interface is completely loaded before it is linked.
��� A class or interface is completely verified and prepared before it is initialized.
��� Errors detected during linkage are thrown at a point in the program where some
action is taken by the program that might, directly or indirectly, require linkage
to the class or interface involved in the error.
��� A symbolic reference to a dynamically-computed constant is not resolved until
either (i) an ldc, ldc_w, or ldc2_w instruction that refers to it is executed, or (ii)
a bootstrap method that refers to it as a static argument is invoked.
��� A symbolic reference to a dynamically-computed call site is not resolved until a
bootstrap method that refers to it as a static argument is invoked."
Specification
-------------
Specific change to archived boot class linking process:
```
At the end of InstanceKlass::restore_unshareable_info, if the
current class' loader is the NULL class loader, the archived
class' '_init_state' is set to be 'linked'.
If JvmtiExport::should_post_class_prepare() is true, the VM
calls JvmtiExport::should_post_class_prepare() to notify JVMTI
agents in SystemDictionary::define_instance_class().
```
webrev: http://cr.openjdk.java.net/~jiangli/8232222/webrev.02/
[1] https://docs.oracle.com/javase/specs/jvms/se14/jvms14.pdf
[2] http://cr.openjdk.java.net/~jiangli/Leyden/Java%20Class%20Pre-resolution%20and%20Pre-initialization%20(OpenJDK).pdf