| name | hotspot-jit-forensics |
|---|---|
| description | Diagnose Java performance issues by inspecting HotSpot bytecode, tiered compilation state, inlining decisions, C2 assembly, compilation limits, and object layout. Produces reproducible artifacts (jit.xml, directives, JFR, disassembly) and links them to actionable code changes. |
A practical playbook for diagnosing Java performance issues by looking at what HotSpot actually does.
Use this skill when you suspect:
- Lost inlining, megamorphic dispatch, or deoptimization.
- A hot method is slow because it never reaches C2.
- High CPU in tiny methods (often a no-inline or missed intrinsic).
- High allocation rate or cache-unfriendly object layout.
- Compilation failures/bailouts (node limits, method too big, deep inlining).
- Code cache pressure, safepoint stalls, or lock contention.
- Collect JVM facts
.codex/skills/hotspot-jit-forensics/scripts/jit-facts.sh --out jit-facts.txtFor a running process:
.codex/skills/hotspot-jit-forensics/scripts/jit-facts.sh --pid <pid> --out jit-facts.txt- Generate a C2 directives file
.codex/skills/hotspot-jit-forensics/scripts/jit-directives.sh \
--method "com/foo/MyClass.myMethod()" \
--out c2-directives.json5- Run the target command with compiler logging
.codex/skills/hotspot-jit-forensics/scripts/jit-run-log.sh \
--directives c2-directives.json5 \
--logfile jit.xml \
-- java -XX:+UnlockDiagnosticVMOptions -jar app.jarArtifacts produced:
jit-facts.txt(version, flags, OS/arch, optional jcmd output)c2-directives.json5(method-scoped compiler diagnostics)jit.xml(HotSpot compilation log)- Console output with inlining and assembly (if
hsdisis available)
Use JFR or async-profiler to identify the actual hot method(s).
Determine if the method is interpreted, C1, or C2.
Runtime:
jcmd <pid> Compiler.codelist | head
jcmd <pid> Compiler.queue
jcmd <pid> Compiler.codecacheStart-up (noisy):
java -XX:+PrintCompilation -jar app.jarPrefer Compiler Directives with a focused match.
HotSpot only prints assembly with the hsdis plugin installed.
Check jit.xml (or JITWatch) for inline failures and compilation bailouts.
Use JOL (CLI or code) and jcmd class histograms.
GC, safepoints, locks, and code cache can dominate CPU.
-XX:+UnlockDiagnosticVMOptions-XX:+LogCompilation -XX:LogFile=jit.xml-XX:+CompilerDirectivesPrint -XX:CompilerDirectivesFile=c2-directives.json5-XX:+PrintCompilation-Xlog:safepoint=info(JDK 9+)-Xlog:gc*(JDK 9+)
Collect JVM + OS facts and optional jcmd diagnostics into one file.
Usage: jit-facts.sh [--pid <pid>] [--out <file>]
Generate a compiler directives file for a target method.
Usage: jit-directives.sh --method <pattern> [--out <file>]
Run a java command with directive-based C2 logging.
Usage: jit-run-log.sh --directives <file> --logfile <file> -- java <args...>
- Repro command line (exact).
- JVM version + flags (
jit-facts.txt). - Profile (
recording.jfrorcpu.svg/alloc.svg). jit.xml(LogCompilation).- directives file (
c2-directives.json5). - Assembly snippet for target method(s).
- Object layout output (JOL internals + footprint).
- Summary: “hypothesis → evidence → change → result”.
- https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html
- https://docs.oracle.com/en/java/javase/12/vm/compiler-control1.html
- https://docs.oracle.com/en/java/javase/12/vm/writing-directives.html
- https://docs.oracle.com/en/java/javase/11/troubleshoot/diagnostic-tools.html
- https://openjdk.org/projects/code-tools/jol/
- https://openjdk.org/jeps/520