HardExperience level: 8-15 years3 min read

Diagnosing High CPU in Production Java — Interview Questions

Reviewed by Gurusankar M.

Asked inAmazonMicrosoftGoogleDeloitte
#cpu profiling#async-profiler#jfr#flame graph#production troubleshooting
Report issue

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

bash
# 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 views

Think 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

  1. How does async-profiler capture native frames that a pure-Java profiler would miss?
  2. How would you distinguish GC-caused CPU from application-caused CPU in a flame graph?
  3. 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.
Open inChatGPTGeminiClaude

Was this answer helpful?

Affiliate links

Equipment for a comfortable, productive setup.

As an Amazon Associate I earn from qualifying purchases.