|
Relates :
|
|
|
Relates :
|
|
|
Relates :
|
|
|
Relates :
|
|
|
Relates :
|
|
JDK-8188791 :
|
|
|
JDK-8188792 :
|
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
-----
- Reduce footprint by sharing common class metadata across different
Java processes.
- Improve startup time.
- Extend CDS to allow archived classes from the JDK's run-time image
file (`$JAVA_HOME/lib/modules`) and the application class path to be
loaded into the built-in platform and system class loaders.
- Extend CDS to allow archived classes to be loaded into custom class
loaders.
Non-Goals
---------
- The shared-class archive storage format used in this implementation
will not be standardized.
- In this release, CDS cannot archive classes from user-defined modules
(such as those specified in `--module-path`). We plan to add that
support in a future release.
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:
- We can save about 340MB of RAM for a Java EE app server that includes
6 JVM processes consuming a total of 13GB of RAM (~2GB of that is for
class meta data).
- We can improve the startup time of the JEdit benchmark by 20-30%.
- We can reduce the RAM usage of the embedded Felix benchmark by 18%
across 4 JVM processes.
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:+UseAppCDS` 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
- *Platform and system class loaders:* The HotSpot VM recognizes
class-loading requests from the built-in platform and system class
loaders. When these loaders request a class that exists in the CDS
archive then the VM skips the usual class-file parsing and
verification steps and loads the archived copied of the class.
- *Custom class loaders:* When a custom class loader invokes
`ClassLoader::defineClass`, the VM attempts to match the contents of
the class file with an archived class by comparing fingerprints of the
class-file data. If a match is found, the VM skips the class-file
parsing and verification steps and directly loads the archived copy of
the class.
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:
- An extra 'dump' step is required.
- When the application's JAR files are updated, the dump step needs to
be repeated.
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.
|