java-profiler helps teams find the Java stack behind a performance problem in a Kubernetes service. It collects real async-profiler/JFR-derived data from HotSpot-compatible JVMs and presents CPU, allocation, lock, thread, GC, and I/O evidence in a service-focused UI.
Use it when your existing monitoring tells you that a Java service is slow, using too much CPU, approaching an OOM kill, pausing for GC, or waiting on locks—but does not show which Java code is responsible.
- Enable profiling with Kubernetes annotations or labels; application code does not need to change.
- Collect CPU, Wall Clock, allocation, lock-delay, Java I/O wait, GC, thread, and deadlock evidence from the target JVM.
- Query the data from ClickHouse with retention capped at seven days.
- Keep metric storage, dashboards, alerting, logs, and tracing in the systems that already own those concerns.
The first version is deliberately limited to Java services on Kubernetes, HotSpot-compatible JVMs, a node-local DaemonSet collector, async-profiler, ClickHouse, and a compact diagnosis UI. Pyroscope, Parca, and Grafana are not required backend dependencies.
Add temporary profiling to the target workload's Pod template:
metadata:
annotations:
java-profiler.io/profile-mode: temporary
java-profiler.io/profile-duration: 15mOpen the Web UI, select the namespace, service, and time range, and check status first. Then choose the view that matches the symptom:
cpufor expensive Java methods;wallfor runnable, blocked, waiting, sleeping, or I/O time that CPU does not explain;iofor Java-owned socket or file blocking;gcfor JVM pause events and their allocation context;memoryfor sampled allocation pressure;locksanddeadlocksfor contention and deadlock cycles;ingestionto confirm that profile batches reached the backend.
See the Quickstart and Performance Analysis Manual.
- CPU hotspots with Self CPU, Total CPU, and sampled stack context.
- Wall Clock latency broken down by runnable, blocked, waiting, sleeping, and I/O paths.
- Java I/O wait when JVM/JFR data preserves ownership of the blocking path.
- GC pause events correlated with allocation profiles in the same time window.
- Sampled allocation totals, top allocating paths, top self-allocating frames, and allocation flamegraph context.
- Lock delay caused by synchronized or monitor paths under contention.
- Thread snapshots for CPU, lock, sleep, blocked, and waiting states.
- Deadlock cycles reported by the target JVM.
- Target and ingestion status that explain disabled profiling, unsupported JVMs, attach failures, conflicts, expired temporary windows, rejected uploads, and dropped data.
Allocation profiles identify where objects are created. They do not provide retained-heap ownership, dominator trees, or a heap-leak analysis.
Kubernetes metadata
|
v
Node-local collector DaemonSet
|
v
async-profiler/JFR + thread diagnostics
|
v
Backend API -> ClickHouse
|
v
Service diagnosis UI
The collector discovers eligible JVMs on its node, starts bounded profiling sessions, and uploads normalized data. The backend stores query-ready profiles and diagnosis records in ClickHouse. The UI keeps the same service, Pod, JVM, profile type, and time-range context as the investigation moves between views.
These screenshots come from a real Kubernetes acceptance environment, not mocked UI state.
- Target status
- CPU profile analysis
- Allocation analysis
- Wall Clock latency
- Java I/O wait
- GC pause and allocation correlation
- Deadlock diagnosis
- Ingestion health
Regenerate the screenshots from a port-forwarded real UI:
export REAL_ACCEPTANCE_BASE_URL=http://127.0.0.1:18081
export REAL_ACCEPTANCE_NAMESPACE=java-profiler-qa
export REAL_ACCEPTANCE_SERVICE=jdk17-http-demo
node scripts/capture-doc-screenshots.mjsRun the relevant checks before changing profiling, ingestion, backend APIs, or UI behavior:
go test ./...
javac --release 11 java-helper/thread-diagnostics/src/main/java/com/ebpfjava/threads/*.java
cd examples/jdk17-http-demo && mvn test
cd ../../web && npm ci && npm test && npm run buildBuild the documentation site with:
cd docs
npm install
npm run docs:buildChanges that touch collector profiling, ingestion, ClickHouse, backend query APIs, deployment, the demo service, or the profile UI also need real Kubernetes acceptance. Start with Contributing and follow the Real Profiling Acceptance Standard.
- Online docs
- 中文文档
- Quickstart
- Analyze a Java service
- Enable profiling
- Deploy and operate the platform
- Development setup
- Localization policy
- Architecture
The first version does not include non-Java profiling, OpenJ9 support, heap-dump analysis, distributed ClickHouse, tracing, log analysis, service maps, dashboarding, alerting, or Prometheus metric storage.
Collectors and backends may expose operational metrics. Prometheus-series services own metric storage, dashboards, alerting, and retention.
