Thread Deadlock Detection
The Nodinite JMX Monitoring Agent doesn't detect thread deadlocks and doesn't count threads. It monitors CPU and free heap per JVM (Configuration). This page explains what a thread deadlock is, what you can and can't expect to see in Nodinite, and how to find a deadlock with standard JVM tools such as jstack and JConsole.
Understanding Thread Deadlocks
A thread deadlock occurs when two or more JVM threads each hold a lock that another thread is waiting to acquire. None of the threads can proceed; they wait indefinitely, and the work they handle stalls. The JVM itself keeps running, and a deadlock doesn't resolve itself: the application usually needs a restart.
Holds Lock 1
Waiting for Lock 2"] B["fa:fa-lock Thread B
Holds Lock 2
Waiting for Lock 1"] A -->|"waiting for"| B B -->|"waiting for"| A style A fill:#c33d34 style B fill:#c33d34
Diagram: Thread deadlock (red, both threads blocked): Thread A waits for Lock 2 held by Thread B, while Thread B waits for Lock 1 held by Thread A.
Common causes are acquiring several locks in inconsistent order across code paths, nested synchronized blocks, and third-party libraries or connectors whose internal locks conflict with application locks.
What the JMX Monitoring Agent Shows During a Deadlock
| Signal | Shown by the JMX Monitoring Agent | Notes |
|---|---|---|
| Deadlocked threads | ❌ No | The agent doesn't read thread information |
| Thread count | ❌ No | The agent doesn't count threads |
| CPU usage | ✅ Yes | Blocked threads use little CPU, so a deadlock often doesn't change CPU at all |
| Free heap | ✅ Yes | Heap may drop if work queues up behind the blocked threads, but that isn't guaranteed |
| JVM reachable | ✅ Yes | The Resource shows Unavailable only if the JVM stops answering JMX, which a deadlock usually doesn't cause |
Important
A JVM Resource can stay OK during a deadlock. Don't rely on the JMX Monitoring Agent to catch deadlocks; watch the work the application does instead, for example with Non-Events Monitoring on expected message volumes or the Web Services Monitoring Agent on the application's endpoints.
Finding a Deadlock with JVM Tools
Generate a Thread Dump with jstack
A thread dump captures the state of all JVM threads at a point in time. Run jstack on the JVM host:
# Find the process ID
jps -l
# Write a thread dump to a file
jstack <PID> > thread-dump.txt
Tip
Capture 2–3 thread dumps about 15 seconds apart. Threads that are blocked in every dump are deadlocked or under heavy lock contention.
Read the Thread Dump
When the JVM finds a deadlock, jstack ends the dump with a summary like this:
Found one Java-level deadlock:
=============================
"Thread-A": waiting to lock monitor 0x00000000f8b3c420
which is held by "Thread-B"
"Thread-B": waiting to lock monitor 0x00000000f8b3c500
which is held by "Thread-A"
Look for BLOCKED (on object monitor) (the thread waits for a lock), waiting to lock <address>, and locked <address> in the stack trace of each blocked thread.
Use JConsole
JConsole connects to the same JMX remote port that the Nodinite JMX Gateway uses. On the Threads tab, click Detect Deadlock to list deadlocked threads and their stack traces.
Resolving Thread Deadlocks
Restart the JVM to release the locks, then capture a thread dump after startup to confirm the deadlock doesn't reappear at once. To prevent recurring deadlocks:
- Consistent lock ordering - Always acquire locks in the same order across all code paths.
- Lock timeouts - Use
ReentrantLock.tryLock(timeout)instead ofsynchronizedblocks so a thread gives up instead of waiting forever. - Reduce lock scope - Keep the code inside synchronized blocks short.
- Thread-safe data structures - Use
java.util.concurrentcollections to reduce explicit locking.
Next Steps
Configuration
OS vs JVM Monitoring
Related Topics
Supported Java Versions
Multi-JVM Monitoring
Heap Used vs Committed
JMX Monitoring Agent
JMX Troubleshooting Overview