Java Performance
Purpose
Turn a vague symptom into a bounded investigation with competing hypotheses, a minimal evidence
set, and the correct specialist owners. Do not route directly from one symptom to one cause:
production regressions frequently combine load mix, queues, GC, compilation, I/O, dependencies,
resource limits, observability, and deployment lifecycle.
This skill should leave context once the investigation protocol and specialist set are clear.
performance-methodology owns the causal workflow from hypothesis through validation.
Triage contract
Before choosing a tool or owner, record:
user/business symptom and SLO impact:
metric definition, unit, aggregation, sample count, source, and clock:
affected percentiles/throughput/errors/cost and time interval:
offered load, completed work, operation/data/tenant mix, concurrency:
affected versions/instances/zones/hosts/clients and healthy controls:
startup/warm/steady/shutdown or incident lifecycle phase:
recent code/config/JDK/dependency/data/infrastructure/deploy changes:
resource demand/limits/queues and downstream health:
recovery deadline and evidence-preservation budget:
Start with available facts and mark unknowns; do not require every field before useful triage.
For missing evidence, state which hypothesis remains unresolved and the smallest artifact or
focused question that would distinguish it. A screenshot or unavailable process can support
a collection plan, not a confirmed mechanism or an invented baseline.
Record the target JDK vendor/build, JVM implementation, collector, OS/container, agents and
profiler versions separately from compiler --release. The linked tool documentation uses
JDK 25/HotSpot; it is not a requirement to upgrade. Check the target's command help, event
metadata and effective settings before transferring commands, flags or event assumptions.
Preview/incubator APIs, attach access and platform-specific profilers need explicit target support.
If the process is degrading and remediation is imminent, invoke incident-evidence-capture
before an ordinary investigation. Bounded capture must fit the recovery deadline: do not delay
already authorized mitigation to complete this checklist or restart merely to enable a tool.
If the measurement cannot be trusted, route first to
latency-statistics, coordinated-omission, load-testing, or
performance-methodology.
First classification
Use four independent axes rather than a single label:
| Axis |
Questions |
| Outcome |
latency distribution, throughput/goodput, errors/timeouts, startup/readiness, cost |
| Demand |
offered versus accepted/completed work, mix, burst, fanout, payload/data size |
| Resource |
CPU user/system/throttled, heap/native/RSS, allocation/GC, disk/network, pools |
| Scope/time |
one/fleet, version/host/zone, transient/permanent/periodic, load/lifecycle correlation |
“CPU low” is not “idle,” “throughput unchanged” is not equal work, and exit 137 is not by itself
proof of OOM. Normalize resource by completed work where meaningful and preserve failures/
timeouts/cancellations.
Evidence selection
Choose the cheapest safe evidence that separates the leading hypotheses in this system.
There is no universal bundle such as “GC log plus two-minute settings=profile JFR.” Existing
continuous logs/JFR/profiles can be cheapest; a new profile/JFR can be inappropriate under disk,
CPU, thread-count, privacy, or recovery pressure.
Useful parallel views, when already available or safely collectable:
- service-level latency/throughput/errors and workload mix;
- per-instance/container/cgroup CPU, memory, pressure, I/O, network, lifecycle;
- GC/JFR/runtime and thread/task evidence;
- dependency/database/queue/pool metrics and traces;
- code/config/JDK/dependency/deployment diff;
- one affected instance versus a genuinely comparable control.
Every collection has a time, overhead, privilege, survivability, and perturbation budget.
Read-only diagnostics can still pause or trigger GC: inspect the target command's documented
impact, not merely whether it changes application data. Keep files on bounded storage that
survives the planned recovery action; use the evidence-capture owner for command selection.
Routing map
| Established question/mechanism |
Primary owner |
| Investigation design, causal experiment, validation |
performance-methodology |
| Metric/percentile/tail validity |
latency-statistics, tail-latency-analysis |
| Load model/generator/omission |
load-testing, load-testing-advanced, coordinated-omission |
| Evidence before restart/OOM/remediation |
incident-evidence-capture |
| Which profiler/event to use |
jfr-and-async-profiler |
| JFR configuration/event internals |
jfr-advanced |
| Existing flame graph interpretation |
flame-graph-analysis |
| Host/kernel gap in JVM evidence |
linux-for-jvm, then ebpf-for-jvm |
| GC confirmed as material path |
gc-log-analysis, jvm-gc-tuning; collector internals as needed |
| Allocation source/lifetime/retention |
allocation-profiling, heap-dump-analysis, java-reference-types-and-leaks |
| Heap/non-heap/native/RSS region |
jvm-memory-regions, metaspace-internals, off-heap-memory |
| Safepoint/TTSP/felt pause mismatch |
safepoints, pause-attribution |
| JIT warm-up/compilation/inlining/deopt/code cache |
jit-compilation and the matching specialist |
| Startup/readiness/checkpoint/AOT |
startup-cds-crac-leyden, graalvm-native-image where relevant |
| Lock/deadlock/liveness/thread state |
concurrency-diagnostics |
| Pools/virtual threads/carriers/pinning |
thread-sizing-and-virtual-threads, virtual-thread-migration, virtual-threads-internals |
| CPU scaling/cache/NUMA/affinity |
cpu-cache-and-numa, numa-and-cpu-affinity, false-sharing-and-contended after evidence |
| Blocking/nonblocking/native I/O path |
blocking-and-nonblocking-io, io-uring-and-zero-copy after evidence |
| Database query/engine/index/ORM/pool/bulk/migration |
database-performance, then the matching specialist |
| Cache topology/effectiveness |
caching-strategies, distributed cache skills as needed |
| Serialization cost |
serialization-performance |
| Instrumentation/tracing cost |
opentelemetry-performance |
| Capacity/queues/concurrency bounds |
littles-law-and-queueing, queueing-models, capacity-planning |
| JDK/runtime migration discontinuity |
jdk-upgrade-impact, jvm-performance-review |
| Microbenchmark or CI gate |
jmh-microbenchmarks, jmh-advanced, performance-regression-ci |
See Triage map for ambiguous symptom forks and
Specialist map for the knowledge graph. The specialist map is
not a mandatory shallow-to-deep ladder; load the minimum skills that own the actual questions.
Core rules
- Classify the measured outcome and work denominator before optimizing.
- Maintain multiple hypotheses until one is discriminated; correlated signals are not
automatically causal.
- A deploy changes more than code: process age/JIT, caches, connections, traffic shifting,
replicas, image/JDK/dependencies/config, data/schema, sidecars, and host placement.
- High latency with low average CPU can be downstream wait, a queue/pool, throttling, pauses,
load-balancer skew, synchronization, network loss, client timing, or idle low demand. Measure.
- Worse scaling with more threads can be locks, shared resources, coherence/NUMA, GC,
oversubscription, quotas, I/O, downstream saturation, or workload change—not automatically
hardware cache effects.
- Pause frequency changes do not prove allocation changed; workload, heap occupancy, sizing,
collector policy, humongous objects, promotion, concurrent-cycle progress, and explicit GC
also matter.
- A restart that “fixes” performance resets much more than JIT/code cache: heap/live state,
pools/connections, caches, leaks, queues, circuit state, load placement, native resources, and
agents.
- A healthy CPU profile does not rule out elapsed wait; a healthy GC log does not rule out
safepoint, OS pause, dependency, or measurement error.
- Never recommend a JVM flag, pool size, cache, virtual threads, SQL index, or architecture
change from symptom shape alone.
Severity and decision path
live user impact and remediation imminent?
-> preserve bounded evidence under incident authority
measurement invalid/ambiguous?
-> repair definition/load/timing/omission before causal analysis
affected cohort and timeline known?
-> compare affected versus compatible controls and recent-change epochs
leading mechanisms identified?
-> collect one discriminating evidence set per surviving branch
mechanism materially contributes?
-> hand off to owner; define intervention and validation
outcome improved under representative/repeated conditions?
-> document evidence, trade-offs, guardrail/regression prevention
Troubleshooting triage failures
| Failure |
Symptom |
Correction |
| Premature routing |
team tunes GC/threads from one dashboard |
restore alternative hypotheses and separating signals |
| Aggregate hides cohort |
fleet mean normal, some users/pods fail |
segment by version/instance/operation/failure domain with cardinality discipline |
| Denominator drift |
CPU/samples rise with traffic or retries |
normalize by accepted/completed work and retain errors/timeouts |
| Lifecycle confound |
only new pods slow |
compare uptime/JIT/cache/readiness/traffic ramp, not steady-state fleet |
| Evidence mismatch |
metrics/JFR/profile use different windows/clocks |
align markers and state uncertainty; recollect if decision-critical |
| Tool perturbation |
capture worsens tail or disappears after drain |
measure overhead; preserve pre-action data; use safer/sparser instrument |
| Restart folklore |
restart helps, code cache blamed |
enumerate every reset state and design a discriminating recurrence test |
Handoff contract
Give the specialist:
precise symptom and affected cohort/window
metric and workload definitions with raw/normalized values
leading hypothesis and alternatives
evidence already collected, provenance, loss, and perturbation
why this evidence routes to that owner
recovery/experiment constraints
success, guardrail, and rollback criteria
Do not hand off only “high CPU” or a screenshot.
Definition of done
For this router, completion means a justified owner and bounded next discriminator, not a
resolved performance incident. Unknowns may remain if their impact and next check are explicit.
Do not keep loading the specialist catalog once one owner can advance the established question.
References
1---2name: java-performance3description: Evidence-first triage and routing for ambiguous Java/JVM performance symptoms: defining the affected population and work, separating latency/throughput/resource/error dimensions, checking measurement and recent-change validity, preserving live-incident evidence, mapping competing hypotheses to discriminating signals, and handing each confirmed mechanism to its owning skill. Use for “it is slow,” regressions, saturation, memory/RSS growth, startup, uneven instances, or post-JDK/deploy changes when the cause is unknown. This is a router, not a substitute for performance-methodology or specialist JVM/OS/database/distributed skills.4---56# Java Performance78## Purpose910Turn a vague symptom into a bounded investigation with competing hypotheses, a minimal evidence11set, and the correct specialist owners. Do not route directly from one symptom to one cause:12production regressions frequently combine load mix, queues, GC, compilation, I/O, dependencies,13resource limits, observability, and deployment lifecycle.1415This skill should leave context once the investigation protocol and specialist set are clear.16`performance-methodology` owns the causal workflow from hypothesis through validation.1718## Triage contract1920Before choosing a tool or owner, record:2122```text23user/business symptom and SLO impact:24metric definition, unit, aggregation, sample count, source, and clock:25affected percentiles/throughput/errors/cost and time interval:26offered load, completed work, operation/data/tenant mix, concurrency:27affected versions/instances/zones/hosts/clients and healthy controls:28startup/warm/steady/shutdown or incident lifecycle phase:29recent code/config/JDK/dependency/data/infrastructure/deploy changes:30resource demand/limits/queues and downstream health:31recovery deadline and evidence-preservation budget:32```3334Start with available facts and mark unknowns; do not require every field before useful triage.35For missing evidence, state which hypothesis remains unresolved and the smallest artifact or36focused question that would distinguish it. A screenshot or unavailable process can support37a collection plan, not a confirmed mechanism or an invented baseline.3839Record the target JDK vendor/build, JVM implementation, collector, OS/container, agents and40profiler versions separately from compiler `--release`. The linked tool documentation uses41JDK 25/HotSpot; it is not a requirement to upgrade. Check the target's command help, event42metadata and effective settings before transferring commands, flags or event assumptions.43Preview/incubator APIs, attach access and platform-specific profilers need explicit target support.4445If the process is degrading and remediation is imminent, invoke `incident-evidence-capture`46before an ordinary investigation. Bounded capture must fit the recovery deadline: do not delay47already authorized mitigation to complete this checklist or restart merely to enable a tool.48If the measurement cannot be trusted, route first to49`latency-statistics`, `coordinated-omission`, `load-testing`, or50`performance-methodology`.5152## First classification5354Use four independent axes rather than a single label:5556| Axis | Questions |57| ---------- | -------------------------------------------------------------------------------------- |58| Outcome | latency distribution, throughput/goodput, errors/timeouts, startup/readiness, cost |59| Demand | offered versus accepted/completed work, mix, burst, fanout, payload/data size |60| Resource | CPU user/system/throttled, heap/native/RSS, allocation/GC, disk/network, pools |61| Scope/time | one/fleet, version/host/zone, transient/permanent/periodic, load/lifecycle correlation |6263“CPU low” is not “idle,” “throughput unchanged” is not equal work, and exit 137 is not by itself64proof of OOM. Normalize resource by completed work where meaningful and preserve failures/65timeouts/cancellations.6667## Evidence selection6869Choose the cheapest **safe** evidence that separates the leading hypotheses in this system.70There is no universal bundle such as “GC log plus two-minute `settings=profile` JFR.” Existing71continuous logs/JFR/profiles can be cheapest; a new profile/JFR can be inappropriate under disk,72CPU, thread-count, privacy, or recovery pressure.7374Useful parallel views, when already available or safely collectable:7576- service-level latency/throughput/errors and workload mix;77- per-instance/container/cgroup CPU, memory, pressure, I/O, network, lifecycle;78- GC/JFR/runtime and thread/task evidence;79- dependency/database/queue/pool metrics and traces;80- code/config/JDK/dependency/deployment diff;81- one affected instance versus a genuinely comparable control.8283Every collection has a time, overhead, privilege, survivability, and perturbation budget.84Read-only diagnostics can still pause or trigger GC: inspect the target command's documented85impact, not merely whether it changes application data. Keep files on bounded storage that86survives the planned recovery action; use the evidence-capture owner for command selection.8788## Routing map8990| Established question/mechanism | Primary owner |91| --------------------------------------------------- | -------------------------------------------------------------------------------------------- |92| Investigation design, causal experiment, validation | `performance-methodology` |93| Metric/percentile/tail validity | `latency-statistics`, `tail-latency-analysis` |94| Load model/generator/omission | `load-testing`, `load-testing-advanced`, `coordinated-omission` |95| Evidence before restart/OOM/remediation | `incident-evidence-capture` |96| Which profiler/event to use | `jfr-and-async-profiler` |97| JFR configuration/event internals | `jfr-advanced` |98| Existing flame graph interpretation | `flame-graph-analysis` |99| Host/kernel gap in JVM evidence | `linux-for-jvm`, then `ebpf-for-jvm` |100| GC confirmed as material path | `gc-log-analysis`, `jvm-gc-tuning`; collector internals as needed |101| Allocation source/lifetime/retention | `allocation-profiling`, `heap-dump-analysis`, `java-reference-types-and-leaks` |102| Heap/non-heap/native/RSS region | `jvm-memory-regions`, `metaspace-internals`, `off-heap-memory` |103| Safepoint/TTSP/felt pause mismatch | `safepoints`, `pause-attribution` |104| JIT warm-up/compilation/inlining/deopt/code cache | `jit-compilation` and the matching specialist |105| Startup/readiness/checkpoint/AOT | `startup-cds-crac-leyden`, `graalvm-native-image` where relevant |106| Lock/deadlock/liveness/thread state | `concurrency-diagnostics` |107| Pools/virtual threads/carriers/pinning | `thread-sizing-and-virtual-threads`, `virtual-thread-migration`, `virtual-threads-internals` |108| CPU scaling/cache/NUMA/affinity | `cpu-cache-and-numa`, `numa-and-cpu-affinity`, `false-sharing-and-contended` after evidence |109| Blocking/nonblocking/native I/O path | `blocking-and-nonblocking-io`, `io-uring-and-zero-copy` after evidence |110| Database query/engine/index/ORM/pool/bulk/migration | `database-performance`, then the matching specialist |111| Cache topology/effectiveness | `caching-strategies`, distributed cache skills as needed |112| Serialization cost | `serialization-performance` |113| Instrumentation/tracing cost | `opentelemetry-performance` |114| Capacity/queues/concurrency bounds | `littles-law-and-queueing`, `queueing-models`, `capacity-planning` |115| JDK/runtime migration discontinuity | `jdk-upgrade-impact`, `jvm-performance-review` |116| Microbenchmark or CI gate | `jmh-microbenchmarks`, `jmh-advanced`, `performance-regression-ci` |117118See [Triage map](references/triage-map.md) for ambiguous symptom forks and119[Specialist map](references/depth-ladder.md) for the knowledge graph. The specialist map is120not a mandatory shallow-to-deep ladder; load the minimum skills that own the actual questions.121122## Core rules123124- Classify the measured outcome and work denominator before optimizing.125- Maintain multiple hypotheses until one is discriminated; correlated signals are not126 automatically causal.127- A deploy changes more than code: process age/JIT, caches, connections, traffic shifting,128 replicas, image/JDK/dependencies/config, data/schema, sidecars, and host placement.129- High latency with low average CPU can be downstream wait, a queue/pool, throttling, pauses,130 load-balancer skew, synchronization, network loss, client timing, or idle low demand. Measure.131- Worse scaling with more threads can be locks, shared resources, coherence/NUMA, GC,132 oversubscription, quotas, I/O, downstream saturation, or workload change—not automatically133 hardware cache effects.134- Pause frequency changes do not prove allocation changed; workload, heap occupancy, sizing,135 collector policy, humongous objects, promotion, concurrent-cycle progress, and explicit GC136 also matter.137- A restart that “fixes” performance resets much more than JIT/code cache: heap/live state,138 pools/connections, caches, leaks, queues, circuit state, load placement, native resources, and139 agents.140- A healthy CPU profile does not rule out elapsed wait; a healthy GC log does not rule out141 safepoint, OS pause, dependency, or measurement error.142- Never recommend a JVM flag, pool size, cache, virtual threads, SQL index, or architecture143 change from symptom shape alone.144145## Severity and decision path146147```text148live user impact and remediation imminent?149 -> preserve bounded evidence under incident authority150151measurement invalid/ambiguous?152 -> repair definition/load/timing/omission before causal analysis153154affected cohort and timeline known?155 -> compare affected versus compatible controls and recent-change epochs156157leading mechanisms identified?158 -> collect one discriminating evidence set per surviving branch159160mechanism materially contributes?161 -> hand off to owner; define intervention and validation162163outcome improved under representative/repeated conditions?164 -> document evidence, trade-offs, guardrail/regression prevention165```166167## Troubleshooting triage failures168169| Failure | Symptom | Correction |170| ---------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------- |171| Premature routing | team tunes GC/threads from one dashboard | restore alternative hypotheses and separating signals |172| Aggregate hides cohort | fleet mean normal, some users/pods fail | segment by version/instance/operation/failure domain with cardinality discipline |173| Denominator drift | CPU/samples rise with traffic or retries | normalize by accepted/completed work and retain errors/timeouts |174| Lifecycle confound | only new pods slow | compare uptime/JIT/cache/readiness/traffic ramp, not steady-state fleet |175| Evidence mismatch | metrics/JFR/profile use different windows/clocks | align markers and state uncertainty; recollect if decision-critical |176| Tool perturbation | capture worsens tail or disappears after drain | measure overhead; preserve pre-action data; use safer/sparser instrument |177| Restart folklore | restart helps, code cache blamed | enumerate every reset state and design a discriminating recurrence test |178179## Handoff contract180181Give the specialist:182183```text184precise symptom and affected cohort/window185metric and workload definitions with raw/normalized values186leading hypothesis and alternatives187evidence already collected, provenance, loss, and perturbation188why this evidence routes to that owner189recovery/experiment constraints190success, guardrail, and rollback criteria191```192193Do not hand off only “high CPU” or a screenshot.194195## Definition of done196197- [ ] Symptom, scope, time, work denominator, lifecycle, and recent changes are explicit.198- [ ] Measurement validity and live-incident evidence risk were checked first.199- [ ] At least plausible alternative hypotheses and discriminating signals are recorded.200- [ ] Affected/control cohorts and resource/dependency views are aligned.201- [ ] Specialist owners are selected by established questions, not presumed causes.202- [ ] No optimization or flag is proposed before material mechanism evidence.203- [ ] Handoff includes validation/rollback criteria and evidence limitations.204205For this router, completion means a justified owner and bounded next discriminator, not a206resolved performance incident. Unknowns may remain if their impact and next check are explicit.207Do not keep loading the specialist catalog once one owner can advance the established question.208209## References210211- [Triage map](references/triage-map.md) — read for competing explanations of an ambiguous symptom.212- [Specialist map](references/depth-ladder.md) — read when the owning question spans domains.213- [Worked example: tail regression after deploy](references/latency-regression.md) — read when214 separating logging, allocation, GC and rollout hypotheses after a deployment.215- [JDK 25 diagnostic command impact](https://docs.oracle.com/en/java/javase/25/docs/specs/man/jcmd.html)216 — consult when budgeting collection, then check help on the target JVM.217- [JDK 25 troubleshooting guide](https://docs.oracle.com/en/java/javase/25/troubleshoot/)218- [JDK Mission Control documentation](https://docs.oracle.com/en/java/java-components/jdk-mission-control/)