Overview

8 Investigating deadlocks with thread dumps

This chapter uses a relatable deadlock story to motivate why Java applications can freeze when threads wait on each other, and explains why thread dumps are the right tool when that happens. A thread dump is a point-in-time snapshot of every thread’s state, stack, and locks, making it ideal when an app is unresponsive, whereas profilers and samplers excel at showing behavior over time. The focus is on learning how to capture these snapshots and interpret them to diagnose deadlocks, high CPU, slowdowns, and other concurrency pathologies—plus how AI can help streamline the analysis without replacing core skills.

You can obtain a thread dump in two main ways. With a profiler (such as VisualVM or JProfiler), it’s typically a single button to capture the dump and often to flag potential deadlocks directly in the UI. From the command line—useful and often necessary in remote or production environments—you first identify the process with jps, then generate the dump with jstack, usually saving the raw text to a file for later analysis in a tool. The chapter demonstrates this on a small app that deliberately deadlocks by nesting synchronized blocks on two shared lists in opposite order, a classic lock-ordering mistake that thread dumps make straightforward to expose.

Reading a raw dump efficiently hinges on a few key fields: thread name plus JVM and native IDs, OS priority, CPU and elapsed times, the state and its description, the stack trace, and the locks held or awaited. To uncover a deadlock, filter to blocked threads, follow the lock identity a thread is waiting on to find the owner, and continue until you either resolve the chain or loop back to the starting thread (indicating a cycle). The chapter distinguishes simple two-thread deadlocks from complex multi-thread cycles, and contrasts them with cascading blocked threads caused by an external wait. While tools such as fastThread and AI assistants can visualize dependencies, highlight suspects, and suggest causes, being able to parse the plain-text dump remains essential for tough scenarios and constrained environments.

If both threads enter the outer synchronized block, but not the inner one, they remain stuck and wait for each other. We say that they went into a deadlock.
When some of the app’s threads get into a deadlock, VisualVM indicates the situation with a message in the Threads tab. Notice that both the _Consumer and _Producer threads are locked on the graphic timeline. To get a thread dump, you simply select the Thread Dump button in the window’s upper-right corner.
A thread dump in plain text that describes an app’s threads. In the thread dump we collected, we can find the two deadlocked threads _Consumer and _Producer.
Follow three simple steps to get a thread dump using the command line. First, find the process ID for which you want the thread dump. Second, use a JDK tool to get the thread dump. Finally, open the thread dump in a profiler tool to read it.
By using the jps tool provided with the JDK, we get the PIDs of the running Java processes. These PIDs are necessary to get thread dumps for a given process.
The jstack command followed by a PID will generate a thread dump for the given process. The thread dump is shown as plain text (also called a raw thread dump). You can collect the text in a file to import it and investigate it later.
Once you save the thread dump into a file, you can open it in various tools to investigate it. For example, to open it in VisualVM, you select File > Load.
To find a deadlock with a thread dump, follow these three easy steps. First, remove all threads that are not blocked. Then, start with one of the blocked threads and find what is blocking it using the lock ID. Continue this process for each thread. If you return to a thread you already investigated, it means you found a deadlock.
When only two threads block each other, it’s called a simple deadlock, but a deadlock can be caused by multiple threads that block each other. More threads means more complexity. Thus, when more than two threads are involved, it's called a complex deadlock.
Cascading locks appear when multiple threads enter a chain where they wait for one another. The last thread in the chain is blocked by an external event, such as reading from a data source or calling an endpoint.
To analyze a thread dump, upload a file containing the thread dump raw data to fastThread.io and wait for the tool to present the details in a simple-to-understand shape.
fastThread provides various details in an easy-to-read format. These details include deadlock detection, dependency graphs, resource consumption, and a flame graph.
After analyzing the thread dump raw data, fastThread identifies and provides details about the deadlock caused by the _Consumer and _Producer threads.

Summary

  • When two or more threads get blocked while waiting for each other, they are in a deadlock. When an app gets into a deadlock, it usually freezes and can’t continue its execution.
  • You can identify the root cause of a deadlock using thread dumps, which show the status of all threads of an app at the time the thread dump was generated. This information allows you to find which thread is waiting for another.
  • A thread dump also shows details such as resource consumption and stack traces for each thread. If these details are sufficient, you can use a thread dump instead of instrumentation for your investigation. Imagine the difference between a thread dump and profiling as the difference between a picture and a movie. With a thread dump, you only have a still image, so you miss the execution dynamics, but you can still get a lot of relevant and helpful details.
  • The thread dump provides information about the threads that were executing in the app when the dump was taken. The thread dump shows essential details about the threads in a plain-text format, including resource consumption, thread state in its life cycle, if the thread is waiting for something, and which locks it’s causing or being affected by.
  • You can generate a thread dump with either a profiler or using the command line. Using a profiling tool to get the thread dump is the easiest approach, but when you can’t connect a profiler to the running process (e.g., due to network constraints), you can use the command line to get the dump. The thread dump will allow you to investigate the running threads and the relationships between them.
  • The plain-text thread dump (also known as a raw thread dump) can be challenging to read. Tools such as fastThread.io help you to visualize the details.

FAQ

What is a thread dump, and why is it useful for investigating deadlocks?A thread dump is a snapshot of all JVM threads at a specific moment. It shows thread states, stack traces, and locks held or waited on. Unlike profilers that sample over time, a dump captures a single instant—ideal when an application is frozen or unresponsive. It helps you see which threads are BLOCKED, who owns the locks, and how threads interact, making deadlocks and bottlenecks easier to diagnose.
How do I get a thread dump with a profiler like VisualVM or JProfiler?Attach the profiler to the running process, open the Threads view, and look for deadlock indicators (e.g., in VisualVM’s Threads tab). Click the “Thread Dump” button to capture the dump as plain text. You can then inspect thread states, stack traces, and locks directly in the tool.
How do I generate a thread dump from the command line on a remote server?Use three steps: 1) Find the Java process ID with jps -l. 2) Generate the dump with jstack <PID> (for example, jstack 14208). 3) Redirect output to a file (e.g., jstack 14208 > dump.txt) and load it into a tool like VisualVM (File > Load) for easier analysis.
What key fields should I read in a plain-text thread dump?Focus on: - Thread name (to identify it) - JVM thread ID (tid) and native OS thread ID (nid) - Priority, CPU time vs elapsed (lifetime) time - State description and state name (e.g., BLOCKED, WAITING, RUNNABLE) - Stack trace (exact code being executed) - Locks held and the lock the thread is waiting to acquire (lock IDs in angle brackets). These reveal who blocks whom and where in the code it happens.
How can inconsistent lock ordering cause a deadlock?If two threads acquire the same locks in opposite order (e.g., one uses listA then listB, the other uses listB then listA), each can enter the first synchronized block and then wait indefinitely for the other lock held by the other thread. Both threads end up waiting for each other, creating a deadlock.
How do I manually confirm a deadlock in a thread dump?Follow three steps: 1) Filter to threads that are BLOCKED or “waiting for monitor entry.” 2) For a blocked thread, note the lock ID it’s waiting for. 3) Find the thread that holds that lock, then see what lock it is waiting for, and continue the chain. If you circle back to the original thread, you’ve found a deadlock cycle.
What’s the difference between simple and complex deadlocks, and what are cascading blocked threads?- Simple deadlock: two threads block each other. - Complex deadlock: a cycle involving three or more threads (A waits on B, B on C, C on A, etc.), harder to trace. - Cascading blocked threads: a chain of waiting threads where the last one is blocked by an external event (e.g., I/O), not by a cycle—so it’s not a deadlock but still a design problem to address.
When should I prefer a thread dump over lock profiling?Use a thread dump when the app is frozen or you only need “what’s happening right now.” Profiling shows execution dynamics over time but can be impractical on locked-up or remote production systems. A dump is quick to capture, easy to move, and often sufficient to pinpoint stuck threads and lock owners.
How can tools like fastThread and AI assistants help analyze thread dumps?fastThread (fastthread.io) visualizes dumps, highlighting deadlocks, dependency graphs, stack traces, resource usage, and flame graphs—making patterns clear without manual parsing. AI assistants can read raw dumps, flag problematic threads/locks, and suggest likely causes. They’re great accelerators, but you should still verify findings since AI can misinterpret edge cases.
What practical tips help avoid and troubleshoot deadlocks in real projects?- Enforce a consistent lock acquisition order across threads. - Keep synchronized sections small and avoid long-running operations inside them. - Be cautious with semaphores, latches, and barriers—misuse can deadlock too. - Give threads meaningful names for easier dump analysis. - Capture multiple dumps over time to see stability of states. - Compare CPU vs elapsed time to spot threads that are alive but not progressing.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Troubleshooting Java, Second Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Troubleshooting Java, Second Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Troubleshooting Java, Second Edition ebook for free