Java applications, especially those running in production, can develop performance bottlenecks, deadlocks, and memory leaks that can be challenging to trace. When these issues arise, quick and effective debugging is essential to keep applications running smoothly and to maintain a positive user experience. This is where VisualVM and JStack become invaluable tools for Java developers.
VisualVM, with its powerful profiling and monitoring capabilities, and jstack, offering detailed thread dumps, are a dynamic duo that enables developers to detect, diagnose, and debug complex issues with ease.
Diagnosing and resolving deadlocks is critical, especially in high-performance applications. This guide will explore how to detect deadlocks and obtain thread dumps using two powerful Java tools: VisualVM and jstack.
Before diving into the tools, let's clarify a few basics:
Deadlock: A situation where threads are waiting for each other to release resources, leading to an indefinite blocking cycle.
Thread Dump: A snapshot of the active threads within a Java application at a given time, including details on their states and any locks they are holding or waiting on. A thread dump is crucial in analyzing and identifying deadlock sources in Java applications, allowing developers to pinpoint the cause of blocked threads.
VisualVM is a visual tool integrating several command-line JDK tools to deliver a comprehensive overview of Java applications. It’s widely used to monitor and profile applications, diagnose memory leaks, and analyze performance.
Connect to the running JVM process.
In the monitoring tools, you can click thread dump or view thread details in real time.
jstack is an invaluable command-line tool for any Java developer dealing with complex applications that rely heavily on threads. By providing detailed insights into thread states, locking behavior, and execution flow, jstack simplifies the debugging process, making it easier to spot and resolve issues like deadlocks, performance bottlenecks, and application freezes.
To capture a thread dump of a running Java application using jstack, you’ll need the process ID (PID) of the Java process. Here’s a step-by-step guide:
C:\Program Files\Java\jdk-21\bin>jps -l 12912 22480 org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp 24020 jdk.jcmd/sun.tools.jps.Jps 14344 org/netbeans/Main 21944 deadlock/deadlock.DeadlockExample
C:\Program Files\Java\jdk-21\bin>jstack 21944 2024-11-02 11:12:18 Full thread dump Java HotSpot(TM) 64-Bit Server VM (21.0.5+9-LTS-239 mixed mode, sharing): Threads class SMR info: . .. .... ... "Thread-0" #29 [18484] prio=5 os_prio=0 cpu=0.00ms elapsed=1896.34s tid=0x000001bb3395ac40 nid=18484 waiting for monitor entry [0x00000099227ff000] java.lang.Thread.State: BLOCKED (on object monitor) at deadlock.DeadlockExample.lambda(deadlock/DeadlockExample.java:23) - waiting to lock <0x000000070d03c740> (a java.lang.Object) - locked <0x000000070d05a828> (a java.lang.Object) at deadlock.DeadlockExample$$Lambda/0x000001bb350019f8.run(deadlock/Unknown Source) at java.lang.Thread.runWith(java.base@21.0.5/Thread.java:1596) at java.lang.Thread.run(java.base@21.0.5/Thread.java:1583) "Thread-1" #30 [23240] prio=5 os_prio=0 cpu=0.00ms elapsed=1896.34s tid=0x000001bb3395b2a0 nid=23240 waiting for monitor entry [0x00000099228ff000] java.lang.Thread.State: BLOCKED (on object monitor) at deadlock.DeadlockExample.lambda(deadlock/DeadlockExample.java:41) - waiting to lock <0x000000070d05a828> (a java.lang.Object) - locked <0x000000070d03c740> (a java.lang.Object) at deadlock.DeadlockExample$$Lambda/0x000001bb35001c08.run(deadlock/Unknown Source) at java.lang.Thread.runWith(java.base@21.0.5/Thread.java:1596) at java.lang.Thread.run(java.base@21.0.5/Thread.java:1583) ... ..... .. Found one Java-level deadlock: ============================= "Thread-0": waiting to lock monitor 0x000001bb117727a0 (object 0x000000070d03c740, a java.lang.Object), which is held by "Thread-1" "Thread-1": waiting to lock monitor 0x000001bb11772500 (object 0x000000070d05a828, a java.lang.Object), which is held by "Thread-0" Java stack information for the threads listed above: =================================================== "Thread-0": at deadlock.DeadlockExample.lambda(deadlock/DeadlockExample.java:23) - waiting to lock <0x000000070d03c740> (a java.lang.Object) - locked <0x000000070d05a828> (a java.lang.Object) at deadlock.DeadlockExample$$Lambda/0x000001bb350019f8.run(deadlock/Unknown Source) at java.lang.Thread.runWith(java.base@21.0.5/Thread.java:1596) at java.lang.Thread.run(java.base@21.0.5/Thread.java:1583) "Thread-1": at deadlock.DeadlockExample.lambda(deadlock/DeadlockExample.java:41) - waiting to lock <0x000000070d05a828> (a java.lang.Object) - locked <0x000000070d03c740> (a java.lang.Object) at deadlock.DeadlockExample$$Lambda/0x000001bb35001c08.run(deadlock/Unknown Source) at java.lang.Thread.runWith(java.base@21.0.5/Thread.java:1596) at java.lang.Thread.run(java.base@21.0.5/Thread.java:1583) Found 1 deadlock.
VisualVM and jstack are two essential tools in the Java developer’s toolkit for diagnosing and troubleshooting Java applications, particularly when dealing with performance issues, deadlocks, and thread bottlenecks.
Together, VisualVM and jstack offer a comprehensive approach to debugging Java applications, with VisualVM providing broad, real-time performance insights and jstack enabling deep thread-level analysis. Their combined usage allows developers to effectively diagnose and resolve complex Java issues in both development and production environments.
A huge thanks to the online documentation, community and all the resources available that made this write-up possible.
The above is the detailed content of Debug and Monitor Java App with VisualVM and jstack. For more information, please follow other related articles on the PHP Chinese website!