Java Performance Tuning in Practice: How to Diagnose Sudden 100% CPU Spikes in Production
When a Java application suddenly hits 100% CPU and becomes unresponsive, this guide walks through a three-step investigation—identifying the hottest process, the most CPU-intensive thread, and the offending code—using tools like top, jstack, and Arthas, and presents common causes and preventive measures.
Classic Three‑Step Investigation
When CPU usage spikes, locate the root cause in three steps: (1) identify the process with the highest %CPU, (2) within that process find the thread consuming the most CPU, (3) examine the thread’s stack trace to pinpoint the offending code. This workflow resolves the majority of incidents.
Hands‑On Demonstration
Step 1 – Identify the culprit process
# top -c # press P to sort by CPUSample output shows a Java process with 96.3 % CPU (PID 29812). Record the PID with the highest %CPU column.
Step 2 – Locate the hottest thread
# top -Hp 29812Sorting by CPU reveals thread PID 29840 using 87.9 % CPU.
Step 3 – Map thread ID to stack trace
# Convert decimal thread ID to hex
printf "%x
" 29840 # outputs: 7490
# Show stack for that thread
jstack 29812 | grep '0x7490' -A 20The stack trace points to YieldingWaitStrategy.applyWaitMethod in the Disruptor library, indicating the waiting strategy is causing the CPU spike.
Common High‑CPU Patterns
Thread.yield() / spin loops – often caused by an unsuitable waiting strategy.
Regex matching – backtracking explosion; optimize the regex or truncate input.
Excessive GC activity – memory pressure; tune heap size or GC policy.
Infinite loops – code defect; review loop conditions.
Lock contention (BLOCKED) – oversized synchronized blocks; shrink lock scope.
Recommended Tool: Arthas
Arthas condenses the three‑step workflow into a single command.
# Download Arthas
curl -O https://arthas.aliyun.com/arthas-boot.jar
# Launch and attach to the Java process
java -jar arthas-boot.jar
# List top 3 CPU‑heavy threads
thread -n 3The output directly shows the stack of the hottest threads without manual hex conversion or grepping.
Real‑World Cases
Case 1 – Regex backtracking explosion
A Spring Boot service experienced 100 % CPU. Arthas revealed the hot thread stuck in java.util.regex.Pattern$CharProperty.match. The root cause was a complex regex applied to overly long request parameters, causing catastrophic backtracking. Replacing the regex with simple string handling eliminated the spike.
Case 2 – Disruptor waiting‑strategy mismatch
A consumer service continuously hit 100 % CPU. The stack showed YieldingWaitStrategy spin‑wait. The issue stemmed from having more consumer threads than CPU cores, making the yielding strategy unsuitable. Switching to BlockingWaitStrategy immediately reduced CPU usage.
Command Cheat Sheet
# Find high‑CPU process
top -c
# Find high‑CPU thread
top -Hp <PID>
# Convert thread ID to hex
printf "%x
" <TID>
# Show stack for that thread
jstack <PID> | grep '0x<hex>' -A 20
# One‑click locate with Arthas
java -jar arthas-boot.jar → thread -n 3Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Coder Trainee
Experienced in Java and Python, we share and learn together. For submissions or collaborations, DM us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
