Diagnosing High CPU in Production Java — Interview Questions
Reviewed by Gurusankar M.
Short Answer
High CPU with no errors means the JVM is legitimately busy doing something — the diagnostic job is figuring out whether that something is your application's hot code, garbage collection, or threads spinning on lock contention, because each has a completely different fix. The modern, low-overhead approach is a CPU flame graph from async-profiler (or JDK Flight Recorder, which ships in the JDK itself) taken directly against the running production process — it samples native and Java stack frames together and renders where CPU time is actually going, which is far more reliable than guessing from a thread dump alone.
On this page
Concept Made Simple
Coffee Chat Question
“A Java service is pegging CPU with no errors logged — how do you find out why?”
Remember It Faster
Mind Map Answer
'High CPU' isn't one problem — it's a symptom with at least three different root causes that look identical from a CPU graph alone: your own code doing real (or wasteful) work, the GC running more than expected, or threads burning cycles spinning on a contended lock instead of blocking. A flame graph is how you tell them apart without guessing.
- Hot application code
- Flame graph shows wide bars in your own method stacks
- GC overhead
- Wide bars in GC threads/frames — points to heap/allocation tuning
- Lock contention
- Threads spinning/blocked — pair CPU profile with thread dumps
- Tools
- async-profiler (flame graphs), JFR (built into the JDK), jstack
Key takeaway: the methodology matters more than any single tool — capture a CPU profile first to see WHERE the cycles go (app code vs GC vs lock spin), then drill into that specific area, rather than starting with a thread dump and guessing.
Learn by Doing
Hands-on Keyboard
# async-profiler: attach to a running JVM, produce a CPU flame graph
./profiler.sh -d 30 -f cpu-profile.html <pid>
# Or use JDK Flight Recorder — built into the JDK, low overhead, safe for prod
jcmd <pid> JFR.start duration=60s filename=recording.jfr
jcmd <pid> JFR.dump filename=recording.jfr
# Open recording.jfr in JDK Mission Control to see CPU, GC and lock-contention viewsThink Beyond the Expected
What If?
What if the flame graph shows most CPU time inside JVM/GC frames rather than your own code?
That points you toward GC tuning rather than application code — check the allocation rate (are you creating far more short-lived objects than expected?), the collector's pause/CPU behavior, and heap sizing, using the same diagnostic path as a dedicated GC-pause investigation rather than treating it as an application logic bug.
Real World
This is a standard on-call runbook step at companies running JVM services at scale: CPU alerts fire, and instead of guessing, the responder pulls a 30-60 second async-profiler or JFR CPU profile directly from the affected pod/instance — safe to do in production because both tools are designed for low overhead — and the flame graph usually points immediately at either a specific hot method, an unexpectedly GC-heavy period, or a lock a thread dump can then confirm.
Real Talk from Guru
My answer to 'how do you debug high CPU' is never 'add print statements and redeploy' — it's 'take a profile of the process that's actually having the problem, right now, in production, with a tool built for that.' That distinction — profiling live instead of trying to reproduce locally — is usually what separates a senior answer here.
Interviewer's Expectation
Keywords they're listening for:
- Distinguishes hot code, GC overhead, and lock contention as separate causes
- Names async-profiler and/or JFR as the tools, not just 'add logging'
- Knows these tools are low-overhead enough for production use
- Describes a methodology (profile first, then drill in), not a single trick
Common Mistakes
- Jumping straight to a thread dump without a CPU profile for context
- Assuming high CPU always means inefficient application code
- Avoiding profiling tools in production due to overhead concerns that don't apply to modern low-overhead profilers
Best Practices
- Take a CPU flame graph (async-profiler or JFR) as the first diagnostic step
- Correlate CPU profiles with thread dumps for lock-contention cases
- Use JFR for its built-in, always-available low overhead in production
Follow-up Questions
- How does async-profiler capture native frames that a pure-Java profiler would miss?
- How would you distinguish GC-caused CPU from application-caused CPU in a flame graph?
- What's the difference between a CPU profile and a wall-clock (latency) profile?
Continue Learning with AI
Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly — AI is your learning companion, not a shortcut.
Plain-language foundations
I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner. Topic: Troubleshooting (JVM) Interview question: "A Java service is pegging CPU with no errors logged — how do you find out why?" Please: 1. Explain the core idea in simple, plain language, using an everyday analogy. 2. Define any technical terms you use. 3. Walk through one small, concrete example. 4. Finish with a single sentence I can easily remember. Keep the tone friendly and assume I'm new to this topic.
Was this answer helpful?
Affiliate links
Tools for Your Developer Workspace
Equipment for a comfortable, productive setup.
As an Amazon Associate I earn from qualifying purchases.
- MonitorView on Amazon : BenQ EW2790U 27-inch Monitor (opens in a new tab)
BenQ EW2790U 27-inch Monitor
- LaptopView on Amazon : Acer Aspire One Laptop (opens in a new tab)
Acer Aspire One Laptop
- Office ChairView on Amazon : Wakefit Gravita Ergonomic Office Chair (opens in a new tab)
Wakefit Gravita Ergonomic Office Chair