Generated banner for Java Diagnostics
Generated logo for Java Diagnostics

Java Diagnostics

GitHubOfficialFirst committed by jduboisDistributed by GitHub

  • Skill
  • Guidelines
  • Software development
  • MIT
  • No issues found

From the author

Symptom-first runtime diagnostics for JVM applications using JDK tools: jcmd, jstack, jmap, jstat, JFR, GC logs, async-profiler, Native Memory Tracking, and Eclipse MAT. Use when a Java app has high CPU, memory leaks or OutOfMemoryError, slow startup, deadlocks or thread starvation, long GC pauses, native memory growth, or slow requests. Includes permission tiers for safe use.
— the description by jdubois

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured, safety-conscious approach to diagnosing common JVM performance issues. It categorizes diagnostic tools into three permission tiers based on their intrusiveness and potential impact on production systems. By following a symptom-first decision table, users can systematically identify and resolve issues such as high CPU usage, memory leaks, thread starvation, and GC pauses. The skill emphasizes safe data collection, user consent for sensitive operations, and local analysis of diagnostic artifacts.

What it does

  • Provides a decision table mapping common JVM symptoms to specific diagnostic tools.
  • Defines three tiers of diagnostic operations based on safety and intrusiveness.
  • Offers guidance on using JDK tools like jcmd, jstack, jmap, and JFR.
  • Includes instructions for profiling with async-profiler and analyzing native memory.
  • Outlines best practices for diagnosing JVM issues within containerized environments.
  • Establishes a workflow for capturing, analyzing, and cleaning up diagnostic data.

When to use it

  • When a Java application experiences high CPU, memory leaks, or OutOfMemoryErrors.
  • When investigating slow startup times or unexplained latency in requests.
  • When diagnosing thread-related issues like deadlocks or thread starvation.
  • When analyzing long GC pauses or native memory growth.
  • When a JVM crashes or hangs and requires post-mortem analysis.

Advantages

  • Promotes safe diagnostic practices by enforcing permission tiers.
  • Reduces trial-and-error by providing a symptom-based diagnostic path.
  • Minimizes production impact by prioritizing non-intrusive tools first.
  • Provides clear guidance on handling sensitive data in heap dumps.
  • Standardizes the diagnostic process across different JVM environments.

Usage examples

“My Java application is experiencing high CPU usage. How should I start diagnosing it?”
The agent will guide you to capture thread dumps using Tier 1 tools and map them to native thread IDs, followed by using JFR or async-profiler for a CPU flame graph.
“I suspect a memory leak in my production JVM. What is the safe way to investigate?”
The agent will instruct you to use Tier 2 tools like jstat and class histograms first, and only proceed to Tier 3 heap dumps with explicit consent and proper precautions.
“How do I diagnose native memory growth in a containerized Java app?”
The agent will suggest comparing RSS versus heap usage, enabling Native Memory Tracking (NMT), and using async-profiler's nativemem mode.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/github/java-diagnostics/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip java-diagnostics.zip -d .agents/skills

Documentation by jdubois

Java Diagnostics

Pick the lightest tool that answers the question, starting from the symptom.

Permission tiers (obey them)

TierToolsRule
1. Read-onlyjps -l, jcmd <pid> help/VM.version/VM.flags/Thread.print, jstat, jstack, reading logsMay run after stating the exact command. Class histograms (jcmd <pid> GC.class_histogram, jmap -histo, jmap -histo:live) are NOT Tier 1: they run heap inspection at a safepoint and can pause application threads on a large heap, so treat them as Tier 2 (consent, stated overhead). The default forms and -histo:live additionally force a full GC; -all=true / jmap -histo skip the full GC but still pause during the scan (and count unreachable objects).
2. Recording / attachJFR (JFR.start, -XX:StartFlightRecording), async-profiler, NMT (-XX:NativeMemoryTracking), enabling GC logsRequires user consent. State duration and expected overhead (JFR default profile is about 1-2%; async-profiler depends on mode; NMT summary roughly 5-10%, detail more) before running.
3. Intrusive / sensitiveHeap dumps (GC.heap_dump, jmap -dump), jhsdb, commands that print JVM arguments or system properties (jps -v/-lv/-m, bare jcmd, VM.system_properties, VM.command_line, jinfo, ps aux on a Java process; they can expose secrets, redact output), JDWP with suspend, anything on productionRequires explicit consent, a stated target path, free-disk check (a dump is about the size of the used heap), and a stated pause. Heap dumps contain secrets (passwords, tokens, personal data). Never share or upload them; redaction is NOT a reliable safeguard. Analyze locally and delete afterwards.

Never run Tier 2 or Tier 3 commands against production unless the user explicitly instructs it. Run diagnostic tools as the same OS user as the target JVM. Prefer reproducing on dev or staging.

Decision table

SymptomFirst stepThenReference
High CPUThread dumps x3 (Tier 1) + top -H to map hot native thread ids to nidJFR or async-profiler CPU flame graph (Tier 2)threads, jfr, async-profiler
Memory leak / OOMjstat -gcutil, GC.class_histogram -all=true twice, minutes apart (Tier 2: safepoint pause even with -all=true; without it a full GC too; get consent on production)Heap dump + Eclipse MAT (Tier 3) or JFR OldObjectSample (Tier 2)heap, gc
Slow startup-Xlog:class+load, framework startup/condition reports, timestamped logsJFR from start, async-profiler wall-clockjfr, async-profiler
Deadlock / thread starvationjcmd <pid> Thread.print (reports deadlocks), compare dumps over timeVirtual threads: Thread.dump_to_filethreads
GC pausesGC log (-Xlog:gc*) and jstat -gcJFR GC events; tune collector/heapgc
Native memory growth (RSS grows, heap does not)Compare RSS vs heap; enable NMT, jcmd VM.native_memory baseline / summary.diff (Tier 2)async-profiler nativemem or allocator toolsnmt, containers
Slow requestsTracing/metrics and logs first; Actuator or Dev UI (see below)JFR (socket/file/lock events), async-profiler wall-clockjfr, async-profiler
JVM crash / hang, no tools respondhs_err_pid*.log, core dumpjhsdb (Tier 3)basics

Start with jps/jcmd basics to identify the target JVM and confirm which JDK version is running.

Workflow

  1. Capture the symptom precisely (when, how often, since which change, JDK version, container limits).

  2. Choose the tier needed; state the command, its overhead, and output location, and get consent for Tier 2/3.

  3. Collect data to a dedicated directory, with timestamps. Prefer several samples over one.

  4. Form a hypothesis from the data, then confirm with a second source (for example a thread dump plus a flame graph).

  5. Fix, re-measure with the same method, and clean up artifacts (dumps, recordings).

Application-level insights (optional)

JDK tools see the JVM; some questions (which endpoint, which SQL query, which bean) are easier at the application level. Optional options, in order of preference:

  • Spring Boot Actuator (metrics, health, loggers, httpexchanges) and Quarkus Dev UI / Micrometer metrics are built in and need no extra tool. Expose Actuator endpoints minimally; For heapdump and threaddump, follow the policy in the spring-observability skill: never expose them over public HTTP; the only exception is a temporary, user-consented window with authentication, TLS and network restriction, removed afterwards.

  • BootUI (https://github.com/jdubois/boot-ui , https://www.julien-dubois.com/boot-ui/): a local-only developer console with an opt-in MCP server for Spring Boot and Quarkus. Optional. Its skill can be installed with gh skill install jdubois/boot-ui skills/bootui.

If considering BootUI:

  • Ask the user for consent before adding any dependency or installing the skill.

  • Use it in a local/dev profile only; never expose it on a network, and never enable its heap dump, thread dump endpoints or MCP server in production.

  • Check the capability and version first (read its README for the supported Spring Boot / Quarkus versions) instead of assuming features.

Follow the project's own documentation for usage; this skill does not reproduce it.

Containers

See containers for attaching tools inside containers, -XX:MaxRAMPercentage, and cgroup memory limits.

References

Official docs (prefer them over this skill for the JDK in use; change 21 to your version): jcmd https://docs.oracle.com/en/java/javase/21/docs/specs/man/jcmd.html, jfr https://docs.oracle.com/en/java/javase/21/docs/specs/man/jfr.html, JFR guide https://docs.oracle.com/en/java/javase/21/jfr/introduction-jdk-flight-recorder.html, troubleshooting guide https://docs.oracle.com/en/java/javase/21/troubleshoot/, async-profiler releases https://github.com/async-profiler/async-profiler/releases.

Files

references/async-profiler.md

Low-overhead sampling profiler (CPU, wall-clock, allocation, lock, native memory) producing flame graphs. Project: https://github.com/async-profiler/async-profiler . Download a pinned release from its GitHub Releases page and verify the checksum (the release API lists a sha256 digest per asset); do not pipe scripts into a shell. State the profiling duration and mode before running. Check the README of the version you use for current flags. The commands below were run against 4.5 (macOS build attached to a running JDK 27 JVM, and the linux-arm64 build attached to a JDK 21 JVM in an eclipse-temurin:21 container); nativemem needs 4.0 or newer, and -e lock prints "No samples were collected" when there is no contention.

Usage (3.x/4.x launcher asprof)

asprof -d 30 -e cpu -f /secure/dir/cpu.html <pid>      # CPU flame graph, 30 s
asprof -d 30 -e wall -t -f wall.html <pid>             # wall-clock per thread (slow requests, startup)
asprof -d 30 -e alloc -f alloc.html <pid>              # allocations
asprof -d 30 -e lock -f lock.html <pid>                # lock contention
asprof -d 60 -e nativemem -f native.html <pid>         # native allocations (4.0+); use -f native.jfr then `jfrconv --nativemem --leak` for leak analysis

Use as a Java agent for startup profiling:

-agentpath:/path/to/libasyncProfiler.so=start,event=cpu,file=/secure/dir/startup.html

The report is written when the JVM exits normally (verified: timeout 5 java -agentpath:... produced the HTML on SIGTERM).

Open the HTML flame graph in a browser: wide frames at the top are where time goes. Use wall for latency (threads blocked on I/O), cpu for CPU burn.

Permissions and caveats

  • cpu mode on Linux uses perf_events. If it fails, check /proc/sys/kernel/perf_event_paranoid (needs a low value, or CAP_PERFMON/CAP_SYS_ADMIN) and kptr_restrict. Changing these sysctls is a host-level security change: ask the user, do not do it silently, and do not do it on shared/production hosts. Without them, use -e ctimer (4.x docs: like cpu but needs no perf_events, no kernel stacks; -e itimer is also accepted and ran in 4.5). In 4.5 in a default Docker Desktop container (perf_event_paranoid=2, no extra capabilities) plain -e cpu, itimer, wall, alloc, lock, nativemem and the -agentpath form all worked without relaxing security, so try the plain command before loosening anything.

  • In Docker the default seccomp profile blocks perf_event_open (the --cap-add SYS_ADMIN / seccomp=unconfined variants were not run); running with relaxed security (--cap-add SYS_ADMIN, --security-opt seccomp=unconfined) weakens isolation: dev only.

  • Attach requires the same user as the JVM. macOS support exists with limitations (no perf events).

  • Flame graphs can expose class and method names from proprietary code; handle accordingly.

  • Debug symbols: enable -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints on the target for more accurate attribution (requires a restart).

Requirements and compatibility

Written for: GitHub Copilot

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an MCP server

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

First committed by
GitHub avatar of jduboisjdubois
Publisher
GitHub (Official)
Distributed by
GitHub
Source
github/awesome-copilot · skills/java-diagnostics · commit 797337f
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Contributors
jdubois

AutoGineer is not affiliated with or endorsed by jdubois or GitHub.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download java-diagnostics.zip