Summary

Extend application class-data sharing 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). 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. However, currently a three-step procedure is required in order to use AppCDS for a Java application:

Do one or more trial runs to create a class list Dump an archive using the created class list 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

: Readable/writable data ro : Read-only data

: 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