Java demo programs for debugging and profiling demonstrations.
Each demo lives in its own directory with self-contained build files, a
README with full instructions, and (where applicable) Python scripting
examples. cd into a demo directory to build, run, record, and debug.
- Java 8+
- Maven 3.6+ or Gradle 7+
- JVM debug symbols — required for Undo recordings to replay correctly.
Many OpenJDK packages ship without native debug symbols, or install them
as a separate package. Run the checker script to verify:
If symbols are missing, install the debug symbols package for your JDK:
./scripts/check-jvm-debug-symbols-sa.sh
Or use a JDK build that includes debug symbols by default (e.g. Adoptium Temurin).sudo apt-get install openjdk-<version>-dbg # Debian/Ubuntu sudo yum debuginfo-install java-<version>-openjdk # RHEL/Fedora
Directory Description
----------------------------- -------------------------------------------------------
concurrent-modification/ Multi-threaded ArrayList modification causes
ConcurrentModificationException
reentrant-modification/ Single-threaded reentrant modification via synchronized
callbacks — all methods are synchronized yet it still
throws ConcurrentModificationException
wait-notify/ Producer silently stops calling notify(), leaving its
consumer stuck in wait() forever
wheres-wally/ Hides "Wally" among 5,000 generated names — target for
precise execution navigation and syscall analysis
mixed-hotspot/ Four distinct CPU workloads that produce different
signatures in Java and native profilers
vega/ Multi-threaded options analytics engine with an
intentional Black-Scholes bisection bug
spring-petclinic-microservices/ Instrumented Spring microservices for distributed
debugging with Undo
Each demo's README covers how to build, run, record with Undo, register an MCP server, and debug with Claude Code.
From any demo directory:
cd concurrent-modification
mvn compile exec:java # Maven
gradle run # GradleSet LR4J_HOME to your lr4j installation directory, and LR4J_KEY to your
Undo license key file:
export LR4J_HOME=/path/to/lr4j
export LR4J_KEY=/path/to/undo.keyLR4J_KEY must point at a PEM-format key file: base64 wrapped in
BEGIN/END markers, conventionally named *.key.
-----BEGIN UNDO KEY-----
SEQMAAAALS1maXJzdF9uYW1lSEQIAAAAVGVzdGZhcm1IRAsAAAAtLWxhc3RfbmFtZQ==
-----END UNDO KEY-----
There are two ways to get one:
- Copy the supplied key file. If your distribution or trial download already
includes a key in the form above, just point
LR4J_KEYat it. - Convert a binary key. Keys issued in raw binary form need wrapping first:
The script base64-encodes the file and adds the markers; the binary content is unchanged, so converting an already-converted key will not work.
./scripts/convert_key.sh /path/to/binary.key ~/undo.key
The recording targets below pass no key. LR4J_KEY is needed on the replay side,
by the tools that take --key — lr4j_mcp and lr4j_profile. Each demo's
.mcp.json passes ${LR4J_KEY} straight through with no fallback, so it must be
exported in the environment you launch Claude Code from, or the MCP server will
fail to start.
Short-lived demos record the entire execution and save on exit:
mvn compile exec:exec -Precord # Maven
gradle runRecord # GradleVega uses signal-controlled recording for long-running operation — see the Vega README.
You can use Claude Code to interactively debug Undo recordings via an MCP server. The general workflow is:
-
Set up your license key (see License key above) and export
LR4J_KEY. -
Record the demo (see above).
-
Register the recording as an MCP server from the demo directory:
claude mcp add DemoName \ -e BRIDGELOG=DemoName-bridge.log \ -- $LR4J_HOME/bin/lr4j_mcp \ --input DemoName.undo \ --key $LR4J_KEYMost demos already ship a
.mcp.jsondoing this, soclaudepicks the server up automatically when launched from the demo directory. -
Launch
claudefrom the demo directory — see each demo's README for suggested prompts.