OpenJDK project · sponsored by the HotSpot Group

Start a JVM from where it left off.

Coordinated Restore at Checkpoint takes an image of a running, warmed-up Java instance and restores from it. The application skips its own start-up: class loading and JIT compilation have already happened.

API org.crac:crac 1.5.0 Upstream openjdk/crac Mailing list crac-dev

Time to first operation

cold start restored from a CRaC image

Spring Boot 103× faster

38 ms restored 3898 ms cold

Quarkus 30× faster

33 ms restored 980 ms cold

Micronaut 22× faster

46 ms restored 1001 ms cold

XML transform 82× faster

53 ms restored 4352 ms cold

Measured by the project on jdk14-crac: Intel i7-5500U laptop, 16 GB RAM, SSD, Linux 5.7.4, in a ubuntu:18.04 based image. Collected with org-crac/utils/full-bench.sh. The absolute numbers are of their time; the ratio between them is the point. Full results and how to reproduce them.

What CRaC is

A standard way to tell a Java program it is being checkpointed

Checkpoint/restore mechanisms can snapshot a process, but a Java application usually holds things a snapshot cannot carry — open sockets, files, pooled connections, timers. CRaC's contribution is a mechanism-agnostic API through which the runtime tells the application a checkpoint is coming, so it can release those things and reacquire them on restore.

The API

org.crac:crac mirrors jdk.crac and degrades to a no-op on a runtime without CRaC support, so an application can depend on it unconditionally.

public class Cache implements Resource {
  public void beforeCheckpoint(Context<? extends Resource> c) {
    // release what cannot survive the image
  }
  public void afterRestore(Context<? extends Resource> c) {
    // reacquire it
  }
}

Implementing the API

First you need a runtime

Java runtimes with CRaC support

CRaC has to be built into the runtime. The upstream project's own builds come first; vendor builds follow, and each vendor documents its own additions.

  • OpenJDK CRaC
    The project's own builds, from the openjdk/crac repository.
    upstream Builds Docs
  • Azul Zulu builds of OpenJDK
    Zulu builds with CRaC, and Azul's own additions documented separately.
    vendor build Builds Docs
  • BellSoft Liberica JDK
    Dedicated Liberica builds with CRaC, as archives and container images.
    vendor build Builds Docs
  • Canonical builds of OpenJDK
    CRaC packaged in the Ubuntu archive, installed and maintained with apt.
    vendor build Builds Docs

How a deployment works

Warm it up once, then start from the image

The image has to come from somewhere, and that shapes the deployment: the application is run and exercised first, and the image it produces becomes part of the bundle that ships.

Run and exercise it

Deploy to a canary environment and send it real requests, so classes load and the JIT compiles.

Checkpoint the running JVM

jcmd <pid> JDK.checkpoint

The image of the JVM and the application becomes part of the deployment bundle.

Restore in production

java -XX:CRaCRestoreFrom=./image

The restored process already has its loaded classes and compiled code.

Used by

Frameworks that already coordinate with CRaC

Each of these releases CRaC support, so an application usually inherits the coordination rather than writing it.

Spring Boot since 3.2

  • CRaC support in the framework as of Spring Boot 3.2
  • Spring Framework coordinates bean lifecycle around the checkpoint

Micronaut

  • A crac feature on micronaut.io/launch
  • Hikari DataSource and Redis coordination
  • Gradle plugin builds the image in one command

And these ship CRaC support of their own

Each links to that project's own documentation of it.