Visit Azul.com Support

Integrating CRaC in your Application

Table of Contents
Need help?
Schedule a consultation with an Azul performance expert.
Contact Us

Depending on the functionality of your application, it 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, you need to add the CRaC dependency, and implement the beforeCheckpoint and afterRestore methods.

Adding the CRaC API

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 Central Repository.

Maven

 
<dependency> <groupId>org.crac</groupId> <artifactId>crac</artifactId> <version>${crac.version}</version> </dependency>

Gradle

 
implementation 'org.crac:crac:${cracVersion}'

Functionality

During runtime, 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.

Implementing the CRaC Resource and Methods

To use the API, you need to identify all classes in your code that are considered "resources". These are the 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, beforeCheckpoint() and afterRestore() which are used as callbacks by the JVM.

 
package my.app; import org.crac.Context; import org.crac.Core; import org.crac.Resource; public class MyClass implements Resource { public MyClass() { Core.getGlobalContext().register(this); } @Override public void beforeCheckpoint(Context<? extends Resource> context) { /* ... */ } @Override public void afterRestore(Context<? extends Resource> context) { /* ... */ } }

The CRaC JavaDoc is available here.

Use Cases

You need to add implementations of the beforeCheckpoint() and afterRestore() methods in the following cases:

  • File access: If a class reads configurations from a file, you must close the file on checkpoint and reopen it again at restore to check configuration updates.

  • Network connections: Close and reopen any open sockets.

  • Database connections: Close any reopen any database connections.

  • Clock changes: Handle sudden changes in the system clock, which might impact things like cache timeouts.

All 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 getGlobalContext() method.

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.

The API also provides the Core.checkpointRestore() method to create a checkpoint programmatically within your application. You can add this call in the flow of your program, where you want the checkpoint to be created. The method returns when the restore is completed. This call can also be done with jcmd <PID or your_app.jar> JDK.checkpoint at any moment during the lifetime of your application, as described in Generating a Checkpoint.