JDK-8213439 : Run class initialization for boot loader classes with registered subgraph archiving entry field during CDS dump time
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 12
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-11-06
  • Updated: 2019-06-23
  • Resolved: 2018-11-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 12
12 b20Fixed
Related Reports
Blocks :  
Relates :  
Description
Claes discovered that the Long cache is not populated during CDS dump time during the work for JDK-8213033. As a result, the Long cache and associated Long objects cannot be archived.

Archiving the Long cache is beneficial for string concatenation, for example. As we now support archiving subgraphs in the closed archive heap region, archiving the remaining primitive box caches can help providing more memory sharing at runtime.

During CDS dump time, we can force initialization for classes with registered subgraph archiving entry field for the boot loader. Running the initializers can populate the static fields for those classes, including the primitive box caches. As a result, it will allow the primitive caches to be archived at dump time.
Comments
Revised change: http://cr.openjdk.java.net/~jiangli/8213439/webrev.00/
07-11-2018

[~dholmes]There are 279 classes being initialized during dump time currently. The initializations are triggered implicitly during java code execution at dump time, for example initializing the module system and calling system loader's loadClass() (for loading classes from the class list). Initializing the classes (and running java code) has no unwanted side effects at runtime, since we do scrub the mirrors and other data before writing out the archived data. [0.301s][info][class,init] 0 Initializing 'java/lang/Object' (0x00000008c0001040) [0.301s][info][class,init] 1 Initializing 'java/lang/CharSequence'(no method) (0x00000008c0001678) [0.301s][info][class,init] 2 Initializing 'java/lang/String' (0x00000008c0001888) [0.304s][info][class,init] 3 Initializing 'java/util/Comparator'(no method) (0x00000008c0015878) [0.304s][info][class,init] 4 Initializing 'java/lang/String$CaseInsensitiveComparator'(no method) (0x00000008c0015a88) [0.305s][info][class,init] 5 Initializing 'java/lang/System' (0x00000008c00028f8) [0.307s][info][class,init] 6 Initializing 'java/lang/reflect/AnnotatedElement'(no method) (0x00000008c0001b00) [0.307s][info][class,init] 7 Initializing 'java/lang/reflect/Type'(no method) (0x00000008c0001f20) [0.307s][info][class,init] 8 Initializing 'java/lang/Class' (0x00000008c0002130) [0.308s][info][class,init] 9 Initializing 'java/lang/ThreadGroup'(no method) (0x00000008c0006e60) [0.310s][info][class,init] 10 Initializing 'java/lang/Thread' (0x00000008c00069b8) [0.312s][info][class,init] 11 Initializing 'java/security/AccessController'(no method) (0x00000008c0016340) [0.312s][info][class,init] 12 Initializing 'java/security/AccessControlContext' (0x00000008c0003c80) [0.314s][info][class,init] 13 Initializing 'java/lang/Module' (0x00000008c0007dc0) [0.317s][info][class,init] 14 Initializing 'java/util/Set'(no method) (0x00000008c0016978) [0.321s][info][class,init] 15 Initializing 'java/lang/Iterable'(no method) (0x00000008c0016558) [0.321s][info][class,init] 16 Initializing 'java/util/Collection'(no method) (0x00000008c0016768) [0.321s][info][class,init] 17 Initializing 'java/util/AbstractCollection'(no method) (0x00000008c0016b88) With the revised proposal, we will only add a few classes (with registered archiving static fields) to be initialized at dump time, for example, java/lang/Long$LongCache.
07-11-2018

What classes are already being initialized at dump time? Selective initialization would have to be done with great care and would be quite fragile with regards to changes in the static initializers. But if it isn't too many classes then ...
07-11-2018

[~dholmes], [~iklam]Thanks for the comments! The proposal is not to archive all initialized static fields. The current approach that only archives the registered static fields will not be changed. The proposal is to force more classes being initialized during dump time (in addition to the ones already being implicitly initialized by executing java code at dump time). I see your point about the issue of calling ik->initialize() in the dump time loading order. How about only explicitly initializing the classes with the static fields (archived subgraph entry points) being registered for archiving? These classes are the identified ones that have no initialization ordering issue and no unwanted side effect. Your additional comments are appreciated!
07-11-2018

I don't think we can blindly initialize classes at dump time. Class initializers may have side effects (a hypothetical class could open a socket connection in its <clinit>, for example). We also cannot blindly archive all static fields of the initialized classes, since they may store environment info specific to the dumping VM's lifetime.
07-11-2018

I don't think this can work as outlined. The initialization order of classes is very specific and is managed by the initialization routines in the VM. You can not just call ik->initialize() in the order that classes are loaded. Further how do you archive instances of classes that static fields refer to after static initialization? You'd be archiving a complete object graph for an initialized VM. In essence this would be like a checkpointing mechanism that dumps an initialized VM and then reloads it and runs from that point to execute the application logic.
07-11-2018

diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -1751,6 +1751,11 @@ // cpCache) are located together. try_link_class(ik, THREAD); guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class"); + + if (ClassLoaderExt::is_boot_classpath(ik->shared_classpath_index())) { + ik->initialize(THREAD); + } + guarantee(!HAS_PENDING_EXCEPTION, "exception in initialize"); } class_count++;
06-11-2018