Ancho is a Java agent that instruments cryptographic method calls using Java Flight Recorder (JFR). It's part of the Spice Labs runtime PQC (Post-Quantum Cryptography) survey pipeline, enabling organizations to discover which cryptographic algorithms are actually being used at runtime.
When attached to a JVM, Ancho:
- Reads a probe configuration (JSON) that specifies which crypto methods to instrument
- Generates custom JFR event classes for each probe at startup
- Instruments target methods using ByteBuddy so that every call emits a JFR event
- JFR records everything — timestamps, stack traces, thread names — with near-zero overhead
The resulting .jfr recording is then parsed by the Spice Labs CLI to produce a runtime cryptography report showing exactly which algorithms your application uses in production.
Static analysis tells you what crypto code exists in your dependencies. Runtime surveys tell you what crypto code actually executes. This matters because:
- Not all bundled crypto is used — a library may contain DES support you never call
- Runtime context is richer — you see TLS cipher suites, certificate chains, and actual call counts
- Post-quantum migration planning — know exactly which quantum-vulnerable algorithms need migration, ranked by usage
Ancho is designed to be used via the Spice Labs CLI, not invoked directly. The CLI handles probe config download, agent extraction, and JFR recording collection automatically:
spice survey runtime my-app --jfr -- java -jar my-app.jar
spice survey runtime my-app --jfr -- mvn test
spice survey runtime my-app --jfr -- gradle testIf you want to attach the agent directly:
java \
-javaagent:ancho.jar=/path/to/probes.json \
-XX:StartFlightRecording=settings=spice-jfr.jfc,dumponexit=true,filename=recording.jfr \
-jar my-app.jarThe agent reads a JSON configuration file specifying which methods to instrument:
{
"version": "1.0.0",
"probes": [
{
"id": "spice.probe.df3970513497",
"class": "com.sun.crypto.provider.DESCipher",
"method": "init",
"descriptor": "(ILjava/security/Key;)V",
"label": "DESCipher init"
}
]
}Probe configurations are generated by Caraway from its analysis of cryptographic implementations across the Maven ecosystem.
| JDK | Agent Loads | Custom JFR Events | Notes |
|---|---|---|---|
| Oracle JDK 8 | ✅ | ❌ | jdk.jfr.Event not available; agent degrades gracefully |
| OpenJDK 8u262+ | ✅ | ✅ | JFR backport includes jdk.jfr.Event |
| JDK 11+ | ✅ | ✅ | Full support |
| JDK 21+ (LTS) | ✅ | ✅ | Recommended |
| JDK 25+ | ✅ | ✅ | Includes PQC algorithms (ML-KEM, ML-DSA) |
The agent JAR targets JDK 8 bytecode (class version 52) so it loads on any JVM version. On JVMs without the jdk.jfr.Event API, the agent logs a warning and exits cleanly — the target application is never affected.
┌─────────────────────────────────────────────┐
│ Target JVM │
│ │
│ ancho.jar (premain) │
│ ├── ProbeConfig → parse probes.json │
│ ├── EventClassGenerator → ASM-generate │
│ │ JFR event classes (one per probe) │
│ ├── ProbeInstaller → ByteBuddy │
│ │ AgentBuilder with type/method │
│ │ matchers for each probe │
│ └── ProbeAdvice → @OnMethodEnter │
│ emits JFR event on every call │
│ │
│ JFR records: spice.probe.* events + │
│ jdk.SecurityProviderService + │
│ jdk.TLSHandshake + jdk.X509Certificate │
└─────────────────────────────────────────────┘
- ByteBuddy handles all bytecode instrumentation — classloader isolation, module boundaries, retransformation
- ASM (ByteBuddy's embedded copy) generates the JFR event classes dynamically
- Gson parses the probe configuration JSON
- All dependencies are shaded to avoid conflicts with the target application's classpath
# Build and run tests
mvn clean verify
# Package the shaded agent JAR
mvn package -DskipTests
# The agent JAR is at target/ancho-<version>.jarRequires JDK 21+ to build (targets JDK 8 bytecode output).
Copyright 2025 Spice Labs, Inc. & Contributors