When a Java application exhibits high CPU usage or becomes unresponsive, diagnosing the root cause requires systematic inspection of thread behavior using native OS tools and JVM utilities.
Identifying High CPU Consumption
First, launch the application in the background:
nohup java -jar JvmProject.jar &
[1] 1790
Use top to identify the process consuming excessive CPU:
top - 08:57:03 up 25 min, 1 user, load average: 0.49, 0.77, 0.58
%Cpu(s): 99.7 us, 0.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1790 root 20 0 2241412 28948 11752 S 99.9 2.9 0:09.24 java
Next, drill down to individual threads within the Java process using ps with hierarchical output:
ps -H -eo pid,tid,%cpu | grep 1790
1790 1790 99.5
1790 1791 0.0
1790 1802 0.1
The thread with TID 1790 is the primary CPU consumer. Convert this decimal thread ID to hexadecimal for matching with JVM output: 1790 → 0x70E.
Generate a full thread dump using jstack:
jstack 1790
...
"thread1" #8 prio=5 os_prio=0 tid=0x00007f1d8c13c000 nid=0x70e runnable [0x00007f1d6988e000]
java.lang.Thread.State: RUNNABLE
at com.aircoinst.Demo1_6.lambda$main$0(Demo1_6.java:7)
at com.aircoinst.Demo1_6$$Lambda$1/1406718218.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
...
The nid=0x70e matches the high-CPU thread identified earlier. The stack trace reveals the problematic line in Demo1_6.java at line 7 — a tight loop or computationally intensive operation causing sustained CPU usage.
Diagnosing Application Hangs and Deadlocks
If the application appears frozen with no output, first confirm the process ID:
jps
1901 jar
1913 Jps
Then generate a thread dump:
jstack 1901
...
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007fde7c004e28 (object 0x00000000f0c674c0, a com.aircoinst.A),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00007fde7c0062c8 (object 0x00000000f0c68a80, a com.aircoinst.B),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.aircoinst.Demo1_7.lambda$main$1(Demo1_7.java:35)
- waiting to lock <0x00000000f0c674c0> (a com.aircoinst.A)
- locked <0x00000000f0c68a80> (a com.aircoinst.B)
"Thread-0":
at com.aircoinst.Demo1_7.lambda$main$0(Demo1_7.java:27)
- waiting to lock <0x00000000f0c68a80> (a com.aircoinst.B)
- locked <0x00000000f0c674c0> (a com.aircoinst.A)
Found 1 deadlock.
The output explicitly identifies a circular lock dependency: Thread-0 holds lock on object B and waits for object A, while Thread-1 holds lock on object A and waits for object B. This mutual blocking prevents either thread from proceeding, resulting in a complete application freeze.
The source lines referenced (27 and 35) indicate the order of synchronized block acquisition — reversing this order or using lock timeouts could resolve the issue.