kan01234 - Software Engineer Notes

Logo

A backend engineer's journey of learning and growth.

View the Project on GitHub kan01234/post

29 August 2025

Solving High CPU Usage in Java Applications

by kan01234

High CPU usage in a Java application is a common but frustrating issue. It can lead to degraded performance, long response times, and even downtime if left unchecked. The good news is that high CPU typically comes from a small number of repeatable patterns.

In this post, we’ll cover the most common causes of high CPU usage in Java applications and the practical solutions for each.


🔎 How to Start Debugging

Before diving into patterns, always start with a systematic approach:

  1. Check which process is consuming CPU
    top -H -p <pid>
    Shows per-thread CPU usage in the Java process.

  2. Map OS thread → Java thread
    • Convert thread ID to hex: printf '%x\n' <tid>
    • Match with jstack <pid> output (nid=0x...).
  3. Analyze with tools
    • Thread dumps for stack traces
    • Async Profiler / JFR for CPU hotspots
    • Monitoring dashboards for trends

Once you’ve isolated the culprit, it usually falls into one of the categories below.


⚡ Common Patterns of High CPU Usage in Java

1. Hot Loops (Busy Waiting)

Pattern:
Code runs in a loop without yielding, often retrying endlessly.
while (!condition) { // no sleep or backoff }

Impact:
Thread spins at 100% CPU.

Solution:


2. I/O Misuse (Socket or File Spinning)

Pattern:
Polling sockets, files, or queues in a tight loop.
while ((bytes = socket.read(buf)) != -1) { // no blocking, no select() }

Impact:
CPU wasted on busy polling instead of waiting.

Solution:


3. Garbage Collection Pressure

Pattern:

Impact:
CPU dominated by GC threads, application slows.

Solution:


4. Lock Contention & Synchronization

Pattern:
Multiple threads fighting for the same lock.
synchronized (shared) { // heavy work }

Impact:
CPU spikes as threads spin or block waiting for locks.

Solution:


5. Inefficient Algorithms or Data Structures

Pattern:

Impact:
CPU usage grows disproportionately with input size.

Solution:


6. Excessive Logging

Pattern:
Heavy logging inside request/response paths.
log.info("Request: {}", payload); // for every request

Impact:
String concatenation, log formatting, and I/O overhead cause CPU burn.

Solution:


7. External Dependencies (Database, Cache, RPC)

Pattern:

Impact:
CPU wasted either in retries or inefficient I/O handling.

Solution:


🧠 Key Takeaways


✅ Conclusion

High CPU usage in Java applications is almost always traceable to a handful of root causes. By combining monitoring, thread dumps, and profiling, you can isolate the culprit quickly and apply targeted fixes:

With a systematic approach, solving high CPU usage becomes less of a panic and more of a repeatable engineering playbook.

tags: java - performance