Bring Java CRaC into your IDE (VSCode and a little bit about IntelliJ IDEA)
After looking at CRaC I thought it would be nice to create checkpoints from within an IDE.
It’s more comfortable, to do it from within the IDE then using the CLI.
Furthermore it may be easier to do it when you start your service every time with the -XX:CRaCCheckpointTo command.
The code is in this commit on GitHub.
Key takeaways
Before I show you how I did it for VSCode here are some takeaways:
- Adding it into IntelliJ doesn’t work. Or at least I couldn’t add it there. The main reason is that IntelliJ tries to add some helpful commands during the startup of a java service. But this leads to conflicts with the CRaC feature and to some errors like:
Flag TieredStopAtLevel cannot be set during restore: -XX:TieredStopAtLevel=1
-
When the application runs in debug mode creating the checkpoint doesn’t work. Which may be a helpful feature.
-
When I restore from a checkpoint and try to do another checkpoint it fails.
Adding it to VSCode
Make use of VSCodes launch.json and tasks.json feature to configure the checkpoint creation/restore.
launch.json
The launch.json will contain a launch configuration to start the application with the correct JDK and the JVM arguments.
{
"preLaunchTask": "build",
"type": "java",
"name": "CRaC - Run",
"request": "launch",
"projectName": "example-spring-boot",
"vmArgs": ["-XX:CRaCCheckpointTo=/home/dennis/code/java/crac-store"],
"javaExec": "/home/dennis/jdk/zulu21.30.23-ca-crac-jdk21.0.1-linux_x64/bin/java",
"mainClass": "",
"args": ["-jar", "${workspaceFolder}/target/example-spring-boot-0.0.1-SNAPSHOT.jar"]
}
Note that when you copy this over to your own project you’ll definitely need to apply changes to some fields.
When you clone the repo, you’ll need to apply changes to the javaExec and let it point to your version of the JDK which supports CRaC.
tasks.json
The tasks.json contains the build command for the launch command and snapshot creation/restore commands.
Add this to the tasks array of the tasks.json.
{
"label": "build",
"type": "shell",
"command": "mvn package",
"problemMatcher": []
},
{
"label": "Create Snapshot",
"type": "shell",
"command": "pid=$(/home/dennis/jdk/zulu21.30.23-ca-crac-jdk21.0.1-linux_x64/bin/jps -lvm | grep 'example-spring-boot' | awk '{print $1}') && /home/dennis/jdk/zulu21.30.23-ca-crac-jdk21.0.1-linux_x64/bin/jcmd $pid JDK.checkpoint"
},
{
"label": "Restore Snapshot",
"type": "shell",
"command": "/home/dennis/jdk/zulu21.30.23-ca-crac-jdk21.0.1-linux_x64/bin/java -XX:CRaCRestoreFrom=/home/dennis/code/java/crac-store"
}
The most complex complex command here is the one in the command field of the Create Snapshot.
This gets the PID of the application which has in this example the name example-spring-boot. Normally, you can just use the application name, but unfortunately when I tried it it didn’t work. So we get the PID by using jps and pass it to the jcmd command to create the checkpoint.
Start the application
In the “Run and Debug” vie select CRaC - Run.
Then you can start the application:
F1 -> Debug: Start Without Debugging
Create a snapshot
F1 -> Tasks: Run Task -> Create Snapshot
Restore from snapshot
F1 -> Tasks: Run Task -> Restore Snapshot
That’s it! :)
Check the GitHub repo to see the full code.