JEP 310: Application Class-Data Sharing

OwnerIoi Lam
Created2017/08/08 22:02
Updated2017/11/16 23:09
TypeFeature
StatusProposed to Target
Componenthotspot / runtime
ScopeImplementation
Discussionhotspot dash dev at openjdk dot java dot net
Priority2
Reviewed byKaren Kinnear, Mikael Vidstedt, Vladimir Kozlov
Endorsed byMikael Vidstedt, Vladimir Kozlov
Release10
Issue8185996

Summary

To improve startup and footprint, extend the existing Class-Data Sharing ("CDS") feature to allow application classes to be placed in the shared archive.

Goals

Non-Goals

Success Metrics

This project will be considered successful if we can achieve (1) significant space saving in the memory used by Java class metadata across multiple JVM processes, and (2) significant startup time improvements.

For illustrative purposes:

These numbers reflect specific benchmarks and may not be generally applicable. The benefit of this work depends on the number of classes loaded by the supported class loaders as well as the heap usage of the application as a whole.

Description

Class-Data Sharing, introduced in JDK 5, allows a set of classes to be pre-processed into a shared archive file that can then be memory-mapped at runtime to reduce startup time. It can also reduce dynamic memory footprint when multiple JVMs share the same archive file.

Currently CDS only allows the bootstrap class loader to load archived classes. Application CDS ("AppCDS") extends CDS to allow the built-in system class loader (a.k.a., the "app class loader"), the built-in platform class loader, and custom class loaders to load archived classes.

Analysis of the memory usage of large-scale enterprise applications shows that such applications often load tens of thousands of classes into the application class loader. Applying AppCDS to these applications will result in memory savings of tens to hundreds of megabytes per JVM process.

Analysis of serverless cloud services shows that many of them load several thousand application classes at start-up. AppCDS can allow these services to start up quickly and improve the overall system response time.

Enabling AppCDS

By default, Class-Data Sharing is enabled only for the JVM's bootstrap class loader. Specify the -XX:+UseAppCDS command-line option to enable class data sharing for the system class loader (a.k.a. "app class loader"), the platform class loader, and other user-defined class loaders.

Determining the classes to archive

An application may be packaged with a large number of classes but use only a fraction of them during normal operation. By archiving only the classes that are used, we can reduce the file storage size and runtime memory usage. To do this, first run the application normally with -Xshare:off, and use the -XX:DumpLoadedClassList command-line option to record all the classes that are loaded.

Note that -XX:DumpLoadedClassList by default includes only the classes loaded by the bootstrap class loader. You should specify the -XX:+AppCDS option so that classes loaded by the system class loader and platform class loader are also included. For example:

java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=hello.lst -cp hello.jar HelloWorld

Creating the AppCDS archive

To create the AppCDS archive, specify the -Xshare:dump -XX:+UseAppCDS command-line options, pass the list of classes with the -XX:SharedClassListFile option, and set the classpath to be the same as used by your application. You should also use the -XX:SharedArchiveFile option to specify the name of the archive file to store the classes. Note that if -XX:SharedArchiveFile is not specified then the archived classes will be stored into the JDK's installation directory, which is typically not what you want to do. For example:

$ java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=hello.lst \
    -XX:SharedArchiveFile=hello.jsa -cp hello.jar

Using the AppCDS archive

Once the AppCDS archive is created, you can use it when starting the application. Do this by specifying the -Xshare:on -XX:+UseAppCDS command-line options, with the -XX:SharedArchiveFile option to indicate the name of the archive file. For example:

$ java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa \
    -cp hello.jar HelloWorld

Classpath mismatch

The classpath used with -Xshare:dump must be the same as, or be a prefix of, the classpath used with -Xshare:on. Otherwise, the JVM will print an error message about the mismatched classpath and refuse to start. To analyze the mismatch, you can add -Xlog:class+path=info to the application's command-line, and the JVM will print out detailed diagnostic information about what classpath is expected, and what classpath is actually used.

Using -Xshare:auto

AppCDS works by memory-mapping the contents of the archive at a fixed address. On some operating systems, especially when address space layout randomization (ASLR) is enabled, the memory-mapping operation may occassionally fail when the required address space is not available. If the -Xshare:on option is specified, the JVM will treat this as an error condition and fail to start. To make your application more resilient in such situations, we recommend that the -Xshare:auto option to be used instead. This way, when the JVM fails to memory-map the archive, it will disable AppCDS and continue to run the application normally.

Please note that -Xshare:auto will also disable AppCDS if there's a classpath mismatch. Therefore, we recommend that you first test with -Xshare:on to ensure there's no classpath mismatch, and then use -Xshare:auto in the production environment.

Listing the Classes Loaded from the AppCDS Archive

To find out what classes have been loaded from the AppCDS archive, you can use the -Xlog:class+load=info command-line option, which prints out the name of each loaded class, as well as from where the class is loaded. Classes loaded from the CDS archive will be printed as source: shared objects file. For example:

$ java -Xshare:on   -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa \
    -cp hello.jar -Xlog:class+load=info HelloWorld | grep HelloWorld
[0.272s][info][class,load] HelloWorld source: shared objects file

Implementation

Alternatives

We considered using a shared-memory region to share classes that are dynamically loaded by multiple live JVM processes, but we found the sharing potential to be lower and the implementation to be more difficult.

We have, instead, chosen to make the application class-data sharing more static:

This is built on top of the existing CDS infrastructure, so the implementation is simpler and we can achieve a higher ratio of sharing with our target use cases.

Testing

Extensive testing is needed to ensure compatibility and confirm performance benefits.

Testing should be performed on all supported platforms. On some platforms (especially Windows/x86) tests may fail if the JVM is unable to map the archive due to Address Space Layout Randomization (ASLR).

Risks and Assumptions

AppCDS was previously implemented in the Oracle JDK for JDK 8 and JDK 9. This JEP moves the source code to the open repository in order to make the feature generally available. Because AppCDS has been extensively tested in JDK 8 and JDK 9, the risk to compatibility and stability is low.