Coordinated Restore at Checkpoint Usage Guidelines
- Using CRaC in Your Application
- Running an Application With CRaC
- Running CRaC on a Linux System
- Running CRaC in a Virtualized Environment (Docker)
- Running CRaC on Windows or macOS
- Example Code
Your application may be ready for CRaC out-of-the-box! The simplest way is trying to generate a checkpoint. When you meet a CheckpointException, (that describes the problematic state in the application), or if you want to have more control, check the "Implementing the CRaC Resource" section.
The library provided by
org.crac is designed to provide a smooth CRaC adoption. Add this library to build an application that uses the CRaC API, to be able to run it on Java runtimes with CRaC, or without any implementation.
You can find the library in the Maven Repository.
org.crac uses reflection to detect the CRaC implementation. When available, all requests to
org.crac are passed to the implementation. Otherwise, requests are forwarded to a dummy implementation.
The dummy implementation allows an application to run but not to use CRaC:
Resources can be registered for notification.
Checkpoint request fails with an exception.
To use the API, you need to identify all classes in your code that are considered "resources": classes that must be notified when a checkpoint is about to be made and when a restore has happened. The API provides an eponymous interface,
Resource, which must be implemented for the identified classes. There are only two methods,
afterRestore() which are used as callbacks by the JVM.
The CRaC JavaDoc is available here.
Example use case:
If a class reads configuration from a file, the file must be closed in the
afterRestore()method, the file can be opened again to check configuration updates.
The same applies to network connections, and you can also use the methods to deal with a sudden change in the system clock, which might impact things like cache timeouts.
Resources in the application must be registered with the JVM, which can be achieved by obtaining a CRaC
Context and using the
register() method. Although you can create your own
Context, the simplest way is to use the global
Context obtained via the Core class’s static
It’s important to register the
Resources in the right order because this order is used to call the
beforeCheckpoint methods. However, the
afterRestore methods are called in the opposite order. This approach simplifies things if there is a particular sequence in which things need to be prepared for a checkpoint; when restoring, there is a predictable inverse sequence.
Currently, the CRaC functionality is only available on Linux/x64 and Linux/Arm64, in version 17 and 21 of Azul Zulu Builds of OpenJDK. This means, for now, you can run an application with CRaC on any system thanks to the crac.org dependency, but only on the specified OS systems the CRaC functionality in the JVM will work.
|Some VMs, like Parallels, cannot run foreign CPU instructions, and you need a build matching your CPU. Some other virtualization environments, like WSL, do not provide a complete feature set of Linux kernel, limiting the CRaC functionality in the current version.
Currently, CRaC is only available on Linux/x64 and Linux/Arm64, in version 17 and 21 of Azul Zulu Builds of OpenJDK, as of the release of April 2023. Only the bundles with
-crac- in the name, have the integrated CRaC functionality.
On the download section of the Azul website, you can use the "Java Package" > "JDK CRaC" filter.
|The JDK archive should be extracted with sudo.
$ sudo tar zxf <jdk>.tar.gz
Start the JVM with an additional flag
-XX:CRaCCheckpointTo so it’s prepared to create a checkpoint:
java -XX:CRaCCheckpointTo=$HOME/crac-image/ -jar my_app.jar
|This eventually generates a set of files in the given directory, which cumulative size will be roughly the size of the JVM resident memory.
Then you can use two ways to trigger the checkpoint:
From outside the JVM, using
Programmatically within your application, by adding a call to
Core.checkpointRestore()in the flow of your program, where you want the checkpoint to be created. The method will return when the restore has been completed.
You need an application in a runnable JAR file.
Create a Dockerfile, based on the following minimum file:FROM ubuntu:20.04 RUN apt-get update -y ADD "https://cdn.azul.com/zulu/bin/zulu17.44.17-ca-crac-jdk17.0.8-linux_x64.tar.gz" /opt/ RUN cd /opt/ && tar -xzf zulu17.44.17-ca-crac-jdk17.0.8-linux_x64.tar.gz && rm zulu17.44.17-ca-crac-jdk17.0.8-linux_x64.tar.gz ENV JAVA_HOME /opt/zulu17.44.17-ca-crac-jdk17.0.8-linux_x64 ENV PATH $JAVA_HOME/bin:$PATH COPY build/libs/my_app.jar /opt/app/my_app.jar
Build the Docker image with:docker build -t my_app_on_crac .
Run a Docker container with:docker run -it --cap-add=CHECKPOINT_RESTORE --cap-add=SYS_PTRACE --rm --name my_app_on_crac \ -v $PWD/crac-files:/opt/crac-files my_app_on_crac \ java -XX:CRaCCheckpointTo=/opt/crac-files -jar /opt/app/my_app.jar
|In order to restore without additional capabilities (see below), you should make java to be PID 1 process.
Leave the shell window open and the application running.
Open another shell window.
In this window run:docker exec my_app_on_crac jcmd PID-OR-NAME JDK.checkpointNote
You can find PID or NAME to provide to
jcmdby executing just
jcmdin the container.
If everything is ok, you see that in the first shell window the checkpoint was created and your application was closed.
Create a Dockerfile with the checkpoint:FROM my_app_on_crac COPY crac-files /opt/crac-files
Build the Docker image withdocker build -t my_app_on_crac_restore .
Run:docker run -it --rm --cap-add=SYS_RESOURCE my_app_on_crac_restore java \ -XX:CRaCRestoreFrom=/opt/crac-files
Your application now starts much faster from the saved checkpoint.
A restore in an unprivileged container (without the SYS_RESOURCE capability) might succeed but we have identified some issues with stability related to the
brk syscall; therefore it is strongly recommended to use this additional capability.
NOTE: You can run the Docker container also on macOS or Windows, as long as the machine you are running it on has a x64 cpu architecture (Intel/AMD).
You can test your CRaC application on Windows or macOS with one of the following approaches:
Run your application in a virtualized Linux system, e.g. following the Docker approach described above. For instance, on macOS you can use Docker, Podman, Parallels, VirtualBox,…
Use an Azul Zulu Build of OpenJDK with CRaC support for development purposes, available for Windows and macOS. These provide a simulated checkpoint/restore mechanism to be used for development and testing.
Within the CRaC project on GitHub, a fully documented "Step-by-step CRaC support for a Jetty app" is provided.