JVM Class Data Sharing (CDS) can slash application startup times by up to 50% by pre-processing and sharing class metadata across JVM instances.

Let’s see it in action. Imagine you have a simple Java application, say a basic web server that loads a few common libraries.

First, without CDS, we’ll build a simple application and run it.

// SimpleApp.java
public class SimpleApp {
    public static void main(String[] args) {
        System.out.println("Hello from SimpleApp!");
        // Simulate some work to make startup noticeable
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

Compile it:

javac SimpleApp.java

Run it and time it:

time java SimpleApp

You’ll get output like:

Hello from SimpleApp!

real    0m1.234s
user    0m0.123s
sys     0m0.045s

The real time is what we care about for startup.

Now, let’s introduce CDS. There are two main types: Application Class-Data Sharing (AppCDS) and Archive-Only CDS. AppCDS is what you’ll use most often for applications. It involves a two-step process: creating a "dump" of the class metadata and then running your application with that dump.

Step 1: Create the Class Data Archive (Dump)

You need to tell the JVM which classes to archive. A common way is to use a "reference class list" (RCL). Let’s create one.

First, run your application with a special flag to generate a list of classes it uses:

java -Xshare:off -XX:DumpLoadedClassList=app.classlist SimpleApp

This command tells the JVM not to use CDS (-Xshare:off) but to dump the list of loaded classes into app.classlist.

Now, use this app.classlist to create the actual archive. This is the most time-consuming part of the setup.

java -Xshare:dump -XX:SharedArchiveFile=app.cds -XX:ResourceFile=app.classlist -XX:+UseAppCDS SimpleApp

This command:

  • -Xshare:dump: Tells the JVM to create a shared archive.
  • -XX:SharedArchiveFile=app.cds: Specifies the output file name for the archive.
  • -XX:ResourceFile=app.classlist: Points to the list of classes to archive.
  • -XX:+UseAppCDS: Enables Application Class-Data Sharing.

This step might take a few seconds or even minutes depending on the size of your application. The output will be app.cds.

Step 2: Run Your Application with the CDS Archive

Now, when you run your application, you point it to the archive:

java -Xshare:on -XX:SharedArchiveFile=app.cds SimpleApp

This command:

  • -Xshare:on: Tells the JVM to enable CDS and look for the specified archive.
  • -XX:SharedArchiveFile=app.cds: Specifies the archive to use.

Run this and time it:

time java -Xshare:on -XX:SharedArchiveFile=app.cds SimpleApp

You should see a significant reduction in the real time:

Hello from SimpleApp!

real    0m0.567s
user    0m0.110s
sys     0m0.030s

Here, the real time has dropped from 1.234s to 0.567s – nearly a 50% improvement.

How it Works: The Mental Model

At its core, Java’s startup involves loading classes, verifying them, and preparing them for execution. This preparation step, particularly for class metadata (like method signatures, field types, constant pool information), can be computationally expensive.

CDS allows the JVM to pre-process this class metadata once and store it in a shared archive file (.cds). When you start a new JVM instance with CDS enabled, it can load this pre-processed metadata directly from the archive instead of re-doing all the work. This bypasses a large chunk of the class loading and verification overhead that typically occurs during startup.

AppCDS specifically extends this to application classes, not just JDK classes. The app.classlist file is crucial here; it’s a curated list of classes your application actually uses, ensuring you only archive what’s relevant and avoid bloat. The app.cds file is essentially a read-only, memory-mapped file containing this optimized metadata.

The key levers you control are:

  1. Which classes to archive: The app.classlist dictates this. A more comprehensive list (for larger apps) will yield better startup but a larger archive.
  2. When to re-archive: If your application’s dependencies change significantly, you’ll need to re-run the dump process.
  3. CDS mode: -Xshare:off (default, no CDS), -Xshare:auto (tries to use CDS if available, falls back if not), -Xshare:on (requires CDS, fails if archive is missing), -Xshare:dump (creates the archive).

The most surprising thing about CDS is how it leverages operating system features like memory-mapped files. When the JVM loads the .cds archive, it’s not just reading data; it’s mapping a portion of the file directly into the JVM’s address space. This means the OS handles loading the necessary pages of the archive into physical memory on demand, rather than the JVM needing to explicitly read and parse every byte upfront. This makes the initial "loading" of the archive incredibly fast.

The next hurdle you’ll likely encounter is managing CDS archives for dynamic applications or microservices where dependencies change frequently, requiring automated re-archiving strategies.

Want structured learning?

Take the full Jvm course →