JDK-8215311 : JEP 350: Dynamic CDS Archives
  • Type: JEP
  • Component: hotspot
  • Sub-Component: runtime
  • Priority: P3
  • Status: Closed
  • Resolution: Delivered
  • Fix Versions: 13
  • Submitted: 2018-12-12
  • Updated: 2021-10-14
  • Resolved: 2019-07-26
Related Reports
Relates :  
Relates :  
Relates :  
Description
Summary
-------

Extend [application class-data sharing](https://openjdk.java.net/jeps/310) to allow the dynamic archiving of classes at the end of Java application execution. The archived classes will include all loaded application classes and library classes that are not present in the default, base-layer CDS archive.

Goals
-----

 - Improve the usability of application class-data sharing ([AppCDS](https://openjdk.java.net/jeps/310)). Eliminate the need for users to do trial runs to create a class list for each application.

 - Static archiving enabled by the `-Xshare:dump` option, using a class list, should continue work. That includes classes for both built-in class loaders and user-defined class loaders.

Non-Goals
---------

 - Only classes loaded during an application’s execution will be archived. A class that exists in a given JAR file but is not loaded during execution will not be archived.

 - Java heap objects created during an application execution will not be dynamically archived.

 - Dynamic archiving will not be done if an application exits abruptly, e.g., if it crashes.


Motivation
----------

Archiving application classes using AppCDS in HotSpot provides additional startup time and memory benefits relative to the [default CDS archive](https://openjdk.java.net/jeps/341). However, currently a three-step procedure is required in order to use AppCDS for a Java application:

 1. Do one or more trial runs to create a class list
 2. Dump an archive using the created class list
 3. Run with the archive

This procedure, moreover, works only for applications that use only builtin class loaders.  There is experimental support for archiving classes loaded by user-defined class loaders in HotSpot, but it is not easy to use. 

Dynamic archiving enabled by a command-line option will simplify AppCDS usage by eliminating trial runs (step 1 above), and will support both builtin class loaders and user-defined class loaders effectively and uniformly. 

A follow-up enhancement to this JEP could perform automatic archive generation during the first run of an application. This would eliminate the explicit archive creation step (step 2 above). The usage of CDS/AppCDS could then be completely transparent and automatic.

Description
-----------

### Supported archive configurations

The following configurations will be supported at run time:

 - Static base archive (the default CDS archive) + dynamic archive — when both archives are mapped successfully
 - Static base archive only — when the dynamic archive cannot be mapped

The dynamic archive currently requires the default CDS archive to be used as the base archive. If the base-layer archive cannot be mapped and used at run time then the top-layer dynamic archive is automatically disabled.

### Archiving classes at exit

A shared archive is dynamically created when an application exits if the `-XX:ArchiveClassesAtExit` option is specified.

The dynamically-generated archive is created on top of the default system archive packaged with the running JDK image. A separate top-layer archive file is generated for each application. The user can specify the filename of the dynamic archive name as the argument to the `-XX:ArchiveClassesAtExit` option. For example, the following command creates `hello.jsa`:

```
% bin/java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
```

To run the same application using this dynamic archive:

```
% bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello
```

### Base-layer dependency

The dynamically created top-layer archive depends upon the base-layer archive (i.e., it contains pointers to base-layer data), so the CRC values of the base archive header and all shared spaces are recorded in the top layer. 

At run time, when the dynamic archive is mapped in, all recorded CRC values are compared with the currently mapped base archive CRC values. If any of the CRC values do not match then the dynamic archive is disabled, without affecting the usage of the currently-mapped base archive.

Using CRC values to check the base-archive dependency is more robust than using file name, size, and timestamp checks. 

### Copying and relocating class metadata

All loaded application classes and library classes (excluding the ones included in the base layer) are dynamically archived in the top layer. Currently, copying and relocating class metadata is done at the end of the application execution and before VM exit. Archived data is cleaned up in order to remove any non-shareable information.
 
For a user-defined class loader the JVM needs to do extra copying before the class loader and its loaded classes are unloaded. The buffered data is copied into shared spaces with the rest of the dynamically-archived class metadata.

### Shared Spaces in dynamic archives

The layout of the dynamic archive is similar to the existing static archive. Metadata is separated into the following four spaces. No “md” space needed.

 - **rw**: Readable/writable data
 - **ro**: Read-only data
 - **mc**: Trampoline

The shared spaces are mapped individually at runtime. The “ro” space is mapped read-only to enable cross-process sharing.

Memory Savings

When you have multiple related processes running on the same host, you can improve memory sharing by using two levels of archives. For example, when you have these programs that share the same set of libraries:

2 processes running with "-cp:lib.jar:foo.jar FooApp"

4 processes running with "-cp:lib.jar:bar.jar BarApp"

you can create a static archive (using a classlist) for only the classes in lib.jar (and other system classes used by these apps). Then, create two different dynamic archives, one for the "foo" app, and the other for the "bar" app.

This way, the static archive can be shared across all 6 processes, and the dynamic archives can be shared among the processes running the same program.

Alternatives
------------

Copying and relocating the class metadata during dynamic archiving could be done immediately after loading a requested class. Relocating class metadata to the archiving spaces could be done at the end of the application execution before VM exit by relocating the data to the archive spaces. 

Testing
-------

 - All existing CDS and AppCDS tests should be executed to ensure that static archiving from the class list works.
 - New tests should be developed to test dynamic archiving with both builtin class loaders and user-defined class loaders.

Comments
[~mr] "Dynamic CDS Archives" seems good. I've updated the title.
18-02-2019

[~ccheung] Looking at this again, I'm wondering if "Dynamic Class Metadata Archive" is really the best title for this JEP. The existing feature is "Application Class-Data Sharing" (JEP 310), which built on "Class-Data Sharing" (way back in JDK 8), and we have the related feature "Default CDS Archives" (JEP 341). May I suggest that a more logical name for this feature is "Dynamic Class-Data Sharing Archives" or, if you prefer something shorter, "Dynamic CDS Archives"?
16-02-2019

[~mr] Thanks for the editing pass. I've made some clarification on the statement in the last paragraph of the Motivation section.
15-02-2019

I've done a basic editing pass to tighten up the wording and fix some formatting. If this looks okay to you then please assign it to me and I'll move it to Candidate. Question: In the last paragraph of the Motivation section you mention "the final delivery of dynamic archiving support that enables automatic archive generation during the first run of an application." Is that for a future JEP, or for this JEP? Please clarify in the text.
14-02-2019

With further thinking on the naming of command-line option for dynamic dumping, I came up with a new idea last night: Use the existing -Xshare:dump/on/auto to control both static (existing dumping method using a static class list) and dynamic dumping. Following are the details. -Xshare:dump =========== 1) If a classlist is explicitly specified in the command line Create an archive using the classlist statically. This is the existing static dumping method. Application specified (if it is specified) on the command line is ignored and not run. Example: java -Xshare:dump -XX:SharedClassListFile=clist -cp hello.jar HelloWorld 2) If no classlist is explicitly specified in the command line 2.1) If no application is specified Create an archive using the default classlist statically. This is the existing static dumping method. Example: java -Xshare:dump 2.2) If an application is specified Create an archive dynamically based on the context of the application execution. This is the new dumping method (dynamic archiving). Example: java -Xshare:dump -cp hello.jar HelloWorld -Xshare:auto =========== 1) If -XX:SharedDynamicArchiveFile=<d_archive> is not explicitly specified in the command line The runtime behavior is the same as today's behavior. 1.1) If -XX:SharedArchiveFile=<s_archive> is specified The specified archive is used if it can be mapped and validated successfully 1.2) If no -XX:SharedArchiveFile=<s_archive> is specified The default CDS archive packaged with the JDK binary is used 2) If -XX:SharedDynamicArchiveFile=<d_archive> is specified in the command line The runtime uses two archives. 2.1) If -XX:SharedArchiveFile=<s_archive> is specified Both 's_archive' and 'd_archive' are used if they can be mapped and validated successfully. Example: java -XX:SharedArchiveFile=base_archive.jsa -XX:SharedDynamicArchiveFile=app_archive.jsa -cp hello.jar HelloWorld 2.2) If -XX:SharedArchiveFile=<s_archive> is not specified The default CDS archive and the 'd_archive' are used if they can be mapped and validated successfully. Example: java -XX:SharedDynamicArchiveFile=app_archive.jsa -cp hello.jar HelloWorld -Xshare:on ======== The -Xshare:on should follow the same rules that are described for -Xshare:auto in the above to use the archives. 1) If -XX:SharedDynamicArchiveFile=<d_archive> is not explicitly specified in the command line The runtime behavior is the same as today's behavior. 1.1) If -XX:SharedArchiveFile=<s_archive> is specified Error is reported if the specified archive cannot be used. 1.2) If no -XX:SharedArchiveFile=<s_archive> is specified Error is reported if the default CDS archive packaged with the JDK binary cannot be used. 2) If -XX:SharedDynamicArchiveFile=<d_archive> is specified in the command line The runtime uses two archives. 2.1) If -XX:SharedArchiveFile=<s_archive> is specified Error is reported for all following cases: - s_archive cannot be used (d_archive is disabled automatically in this case) - s_archive can be used, but d_archive cannot be used Example: java -XX:SharedArchiveFile=base_archive.jsa -XX:SharedDynamicArchiveFile=app_archive.jsa -cp hello.jar HelloWorld 2.2) If -XX:SharedArchiveFile=<s_archive> is not specified Error is reported if for all following cases: - The default CDS archive cannot be used (d_archive is disabled automatically in this case) - The default CDS archive can be used, but d_archive cannot be used Example: java -XX:SharedDynamicArchiveFile=app_archive.jsa -cp hello.jar HelloWorld The design described above provides a flexible solution that adds the dynamic archiving using the existing command-line options (users are already familiar with). It is backward compatible and simple to use.
19-01-2019