jstack用法

本文继续介绍Java自带的性能监测工具,本文使用jstack (Java Stack Trace)工具来玩~

使用jstack命令工具可以得到线程堆栈信息,根据这些线程堆栈信息,我们可以去检查Java程序出现的问题,如检测死锁,并输出死锁的信息~的排查。

在使用jstack命令之前,可以先使用jstack -h来查看jstack命令相关的使用方法,包括有哪些参数等~

[root@dev18 ~]# jstack -h
Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message

jstack基本语法

  jstack [option] <pid>

使用jstack -m <pid>打印java和native frames 的信息,如jstack -m 12905,这里的12905是Zookeeper服务的进程ID~

[root@dev18 ~]# jstack -m 12905
Attaching to process ID 12905, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.71-b01
Deadlock Detection:

No deadlocks found.

----------------- 12908 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad07875a5 Unsafe_Park + 0x125
0x00007fcacc4b17f8 * sun.misc.Unsafe.park(boolean, long) bci:0 (Interpreted frame)
0x00007fcacc4a5058 * java.util.concurrent.locks.LockSupport.park(java.lang.Object) bci:14 line:186 (Interpreted frame)
0x00007fcacc4a5058 * java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt() bci:1 line:834 (Interpreted frame)
0x00007fcacc4a5350 * java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(int) bci:72 line:994 (Interpreted frame)
0x00007fcacc4a5058 * java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(int) bci:24 line:1303 (Interpreted frame)
0x00007fcacc4a5058 * java.util.concurrent.CountDownLatch.await() bci:5 line:236 (Interpreted frame)
0x00007fcacc4a5058 * org.apache.zookeeper.server.ZooKeeperServerMain.runFromConfig(org.apache.zookeeper.server.ServerConfig) bci:134 line:122 (Interpreted frame)
0x00007fcacc4a5058 * org.apache.zookeeper.server.ZooKeeperServerMain.initializeAndRun(java.lang.String[]) bci:49 line:87 (Interpreted frame)
0x00007fcacc4a5058 * org.apache.zookeeper.server.ZooKeeperServerMain.main(java.lang.String[]) bci:10 line:53 (Interpreted frame)
0x00007fcacc4a5058 * org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(java.lang.String[]) bci:84 line:116 (Interpreted frame)
0x00007fcacc4a5058 * org.apache.zookeeper.server.quorum.QuorumPeerMain.main(java.lang.String[]) bci:10 line:78 (Interpreted frame)
0x00007fcacc49f4e7 <StubRoutines>
0x00007fcad040a085 _ZN9JavaCalls11call_helperEP9JavaValueP12methodHandleP17JavaCallArgumentsP6Thread + 0x365
0x00007fcad0408ae8 _ZN9JavaCalls4callEP9JavaValue12methodHandleP17JavaCallArgumentsP6Thread + 0x28
0x00007fcad0442a99 _ZL17jni_invoke_staticP7JNIEnv_P9JavaValueP8_jobject11JNICallTypeP10_jmethodIDP18JNI_ArgumentPusherP6Thread + 0x219
0x00007fcad044b6b2 jni_CallStaticVoidMethod + 0x162
0x00007fcad0c866d9 JavaMain + 0x7e9
----------------- 12909 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad05eb5cf _ZN7Monitor5IWaitEP6Threadl + 0xef
0x00007fcad05ebd5e _ZN7Monitor4waitEblb + 0x22e
0x00007fcad035fcc3 _ZN13GCTaskManager8get_taskEj + 0x43
0x00007fcad0361388 _ZN12GCTaskThread3runEv + 0x188
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12910 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad05eb5cf _ZN7Monitor5IWaitEP6Threadl + 0xef
0x00007fcad05ebd5e _ZN7Monitor4waitEblb + 0x22e
0x00007fcad035fcc3 _ZN13GCTaskManager8get_taskEj + 0x43
0x00007fcad0361388 _ZN12GCTaskThread3runEv + 0x188
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12911 -----------------
0x000000358d40ba0e __pthread_cond_timedwait + 0x13e
0x00007fcad05eb87e _ZN7Monitor5IWaitEP6Threadl + 0x39e
0x00007fcad05ebd5e _ZN7Monitor4waitEblb + 0x22e
0x00007fcad07b1ff9 _ZN8VMThread4loopEv + 0x339
0x00007fcad07b2300 _ZN8VMThread3runEv + 0x70
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12912 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad061860d _ZN13ObjectMonitor4waitElbP6Thread + 0x9bd
0x00007fcad0487578 JVM_MonitorWait + 0x168
0x00007fcacc52dec8 <Unknown compiled code>
0x00007fcacc4a5058 * java.lang.Object.wait() bci:2 line:503 (Interpreted frame)
0x00007fcacc4a5058 * java.lang.ref.Reference$ReferenceHandler.run() bci:46 line:133 (Interpreted frame)
0x00007fcacc49f4e7 <StubRoutines>
0x00007fcad040a085 _ZN9JavaCalls11call_helperEP9JavaValueP12methodHandleP17JavaCallArgumentsP6Thread + 0x365
0x00007fcad0408ae8 _ZN9JavaCalls4callEP9JavaValue12methodHandleP17JavaCallArgumentsP6Thread + 0x28
0x00007fcad0408db7 _ZN9JavaCalls12call_virtualEP9JavaValue11KlassHandleP6SymbolS4_P17JavaCallArgumentsP6Thread + 0x197
0x00007fcad0408ed7 _ZN9JavaCalls12call_virtualEP9JavaValue6Handle11KlassHandleP6SymbolS5_P6Thread + 0x47
0x00007fcad0485ef5 _ZL12thread_entryP10JavaThreadP6Thread + 0xe5
0x00007fcad076392f _ZN10JavaThread17thread_main_innerEv + 0xdf
0x00007fcad0763a35 _ZN10JavaThread3runEv + 0xf5
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12913 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad061860d _ZN13ObjectMonitor4waitElbP6Thread + 0x9bd
0x00007fcad0487578 JVM_MonitorWait + 0x168
0x00007fcacc52dec8 <Unknown compiled code>
0x00007fcacc4a5058 * java.lang.ref.ReferenceQueue.remove(long) bci:44 line:135 (Interpreted frame)
0x00007fcacc4a5233 * java.lang.ref.ReferenceQueue.remove() bci:2 line:151 (Interpreted frame)
0x00007fcacc4a5233 * java.lang.ref.Finalizer$FinalizerThread.run() bci:36 line:209 (Interpreted frame)
0x00007fcacc49f4e7 <StubRoutines>
0x00007fcad040a085 _ZN9JavaCalls11call_helperEP9JavaValueP12methodHandleP17JavaCallArgumentsP6Thread + 0x365
0x00007fcad0408ae8 _ZN9JavaCalls4callEP9JavaValue12methodHandleP17JavaCallArgumentsP6Thread + 0x28
0x00007fcad0408db7 _ZN9JavaCalls12call_virtualEP9JavaValue11KlassHandleP6SymbolS4_P17JavaCallArgumentsP6Thread + 0x197
0x00007fcad0408ed7 _ZN9JavaCalls12call_virtualEP9JavaValue6Handle11KlassHandleP6SymbolS5_P6Thread + 0x47
0x00007fcad0485ef5 _ZL12thread_entryP10JavaThreadP6Thread + 0xe5
0x00007fcad076392f _ZN10JavaThread17thread_main_innerEv + 0xdf
0x00007fcad0763a35 _ZN10JavaThread3runEv + 0xf5
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12914 -----------------
0x000000358d40d9b0 sem_wait + 0x30
0x00007fcad0622365 _ZL19signal_thread_entryP10JavaThreadP6Thread + 0x95
0x00007fcad076392f _ZN10JavaThread17thread_main_innerEv + 0xdf
0x00007fcad0763a35 _ZN10JavaThread3runEv + 0xf5
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12915 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad05eb5cf _ZN7Monitor5IWaitEP6Threadl + 0xef
0x00007fcad05ebdd6 _ZN7Monitor4waitEblb + 0x2a6
0x00007fcad0254d88 _ZN12CompileQueue3getEv + 0x128
0x00007fcad0258e8a _ZN13CompileBroker20compiler_thread_loopEv + 0x13a
0x00007fcad076392f _ZN10JavaThread17thread_main_innerEv + 0xdf
0x00007fcad0763a35 _ZN10JavaThread3runEv + 0xf5
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12916 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad05eb5cf _ZN7Monitor5IWaitEP6Threadl + 0xef
0x00007fcad05ebdd6 _ZN7Monitor4waitEblb + 0x2a6
0x00007fcad0254d88 _ZN12CompileQueue3getEv + 0x128
0x00007fcad0258e8a _ZN13CompileBroker20compiler_thread_loopEv + 0x13a
0x00007fcad076392f _ZN10JavaThread17thread_main_innerEv + 0xdf
0x00007fcad0763a35 _ZN10JavaThread3runEv + 0xf5
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12917 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad05eb5cf _ZN7Monitor5IWaitEP6Threadl + 0xef
0x00007fcad05ebd5e _ZN7Monitor4waitEblb + 0x22e
0x00007fcad06b9f27 _ZN13ServiceThread20service_thread_entryEP10JavaThreadP6Thread + 0x197
0x00007fcad076392f _ZN10JavaThread17thread_main_innerEv + 0xdf
0x00007fcad0763a35 _ZN10JavaThread3runEv + 0xf5
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12918 -----------------
0x000000358d0df143 __libc_poll + 0x53
0x00007fcac4827037 Java_java_net_PlainSocketImpl_socketAccept + 0x1e7
0x00007fcacc4b17f8 * java.net.PlainSocketImpl.socketAccept(java.net.SocketImpl) bci:0 (Interpreted frame)
0x00007fcacc4a5058 * java.net.AbstractPlainSocketImpl.accept(java.net.SocketImpl) bci:7 line:398 (Interpreted frame)
0x00007fcacc4a5058 * java.net.ServerSocket.implAccept(java.net.Socket) bci:60 line:530 (Interpreted frame)
0x00007fcacc4a5058 * java.net.ServerSocket.accept() bci:48 line:498 (Interpreted frame)
0x00007fcacc4a5233 * sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop() bci:55 line:388 (Interpreted frame)
0x00007fcacc4a5058 * sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run() bci:1 line:360 (Interpreted frame)
0x00007fcacc4a5706 * java.lang.Thread.run() bci:11 line:745 (Interpreted frame)
0x00007fcacc49f4e7 <StubRoutines>
0x00007fcad040a085 _ZN9JavaCalls11call_helperEP9JavaValueP12methodHandleP17JavaCallArgumentsP6Thread + 0x365
0x00007fcad0408ae8 _ZN9JavaCalls4callEP9JavaValue12methodHandleP17JavaCallArgumentsP6Thread + 0x28
0x00007fcad0408db7 _ZN9JavaCalls12call_virtualEP9JavaValue11KlassHandleP6SymbolS4_P17JavaCallArgumentsP6Thread + 0x197
0x00007fcad0408ed7 _ZN9JavaCalls12call_virtualEP9JavaValue6Handle11KlassHandleP6SymbolS5_P6Thread + 0x47
0x00007fcad0485ef5 _ZL12thread_entryP10JavaThreadP6Thread + 0xe5
0x00007fcad076392f _ZN10JavaThread17thread_main_innerEv + 0xdf
0x00007fcad0763a35 _ZN10JavaThread3runEv + 0xf5
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12919 -----------------
0x000000358d40ba0e __pthread_cond_timedwait + 0x13e
0x00007fcad05eb87e _ZN7Monitor5IWaitEP6Threadl + 0x39e
0x00007fcad05ebd5e _ZN7Monitor4waitEblb + 0x22e
0x00007fcad075f951 _ZNK13WatcherThread5sleepEv + 0x71
0x00007fcad075fe6e _ZN13WatcherThread3runEv + 0x5e
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12920 -----------------
0x000000358d0e8f63 __GI_epoll_wait + 0x33
0x00007fcacc5233d2 <Unknown compiled code>
----------------- 12921 -----------------
0x000000358d40ba0e __pthread_cond_timedwait + 0x13e
0x00007fcad0617eab _ZN13ObjectMonitor4waitElbP6Thread + 0x25b
0x00007fcad0487578 JVM_MonitorWait + 0x168
0x00007fcacc52dec8 <Unknown compiled code>
----------------- 12922 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad07875a5 Unsafe_Park + 0x125
0x00007fcacc545e4a <Unknown compiled code>
----------------- 12923 -----------------
0x000000358d40b63c __pthread_cond_wait + 0xcc
0x00007fcad07875a5 Unsafe_Park + 0x125
0x00007fcacc545e4a <Unknown compiled code>
----------------- 17907 -----------------
0x000000358d40eadd __libc_accept + 0x2d
0x00007fcad010972b _ZN14AttachListener7dequeueEv + 0x7b
0x00007fcad010827a _ZL28attach_listener_thread_entryP10JavaThreadP6Thread + 0x19a
0x00007fcad076392f _ZN10JavaThread17thread_main_innerEv + 0xdf
0x00007fcad0763a35 _ZN10JavaThread3runEv + 0xf5
0x00007fcad062a4b8 _ZL10java_startP6Thread + 0x108
----------------- 12905 -----------------
0x000000358d4082ad pthread_join + 0x10d
[root@dev18 ~]# 

 

接下来,我们就来看一下jstack查看死锁的示例~

使用jstack查看死锁

死锁Java代码

public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s"
                + "  has bowed to me!%n", 
                this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

查看死锁进程

在Eclipse上运行上述Deadlock程序,然后使用jps -l查看死锁进程ID~

C:\Users\wangmengjun>jps -l
5752 sun.tools.jps.Jps
16724 F:\JavaDeveloper\eclipse\\plugins/org.eclipse.equinox.launcher_1.3.100.v20150511-1540.jar
11172 Deadlock
17868

使用jstack检测死锁原因

使用jps -l查看死锁进程ID,我们得知死锁程序的PID为11172~

接下来,我们就使用jstack -l 11172检测死锁原因~

C:\Users\wangmengjun>jstack -l 11172
2017-03-22 19:06:29
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):

”DestroyJavaVM” prio=6 tid=0x0000000002a72800 nid=0x3d8c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

”Thread-1” prio=6 tid=0x0000000011373000 nid=0x46c4 waiting for monitor entry [0x00000000118df000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at Deadlock$Friend.bowBack(Deadlock.java:19)
        - waiting to lock <0x00000007ab134018> (a Deadlock$Friend)
        at Deadlock$Friend.bow(Deadlock.java:16)
        - locked <0x00000007ab134060> (a Deadlock$Friend)
        at Deadlock$2.run(Deadlock.java:34)
        at java.lang.Thread.run(Unknown Source)

   Locked ownable synchronizers:
        - None

”Thread-0” prio=6 tid=0x000000000f9c7800 nid=0x2f94 waiting for monitor entry [0x00000000117df000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at Deadlock$Friend.bowBack(Deadlock.java:19)
        - waiting to lock <0x00000007ab134060> (a Deadlock$Friend)
        at Deadlock$Friend.bow(Deadlock.java:16)
        - locked <0x00000007ab134018> (a Deadlock$Friend)
        at Deadlock$1.run(Deadlock.java:31)
        at java.lang.Thread.run(Unknown Source)

   Locked ownable synchronizers:
        - None

”Service Thread” daemon prio=6 tid=0x000000000f987000 nid=0x3480 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

”C2 CompilerThread1” daemon prio=10 tid=0x000000000f978000 nid=0x4468 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

”C2 CompilerThread0” daemon prio=10 tid=0x000000000f972800 nid=0x4558 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

”Attach Listener” daemon prio=10 tid=0x000000000f971800 nid=0x4ba4 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

”Signal Dispatcher” daemon prio=10 tid=0x000000000f96e800 nid=0x4860 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None

”Finalizer” daemon prio=8 tid=0x000000000f921000 nid=0x4964 in Object.wait() [0x0000000010cdf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007ab084858> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        - locked <0x00000007ab084858> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)

   Locked ownable synchronizers:
        - None

”Reference Handler” daemon prio=10 tid=0x000000000f917800 nid=0x30bc in Object.wait() [0x0000000010bdf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000007ab084470> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:503)
        at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
        - locked <0x00000007ab084470> (a java.lang.ref.Reference$Lock)

   Locked ownable synchronizers:
        - None

”VM Thread” prio=10 tid=0x000000000f912000 nid=0x3330 runnable

”GC task thread#0 (ParallelGC)” prio=6 tid=0x0000000002a88800 nid=0x4870 runnable

”GC task thread#1 (ParallelGC)” prio=6 tid=0x0000000002a8a000 nid=0x4324 runnable

”GC task thread#2 (ParallelGC)” prio=6 tid=0x0000000002a8c000 nid=0x41d4 runnable

”GC task thread#3 (ParallelGC)” prio=6 tid=0x0000000002a8d800 nid=0x26d4 runnable

”VM Periodic Task Thread” prio=10 tid=0x000000000f991000 nid=0x17a4 waiting on condition

JNI global references: 122






Found one Java-level deadlock:

”Thread-1”:
waiting to lock monitor 0x000000000f91efa8 (object 0x00000007ab134018, a Deadlock$Friend),
which is held by ”Thread-0”
”Thread-0”:
waiting to lock monitor 0x000000000f920398 (object 0x00000007ab134060, a Deadlock$Friend),
which is held by ”Thread-1”

Java stack information for the threads listed above:

”Thread-1”:
at Deadlock$Friend.bowBack(Deadlock.java:19)
- waiting to lock <0x00000007ab134018> (a Deadlock$Friend)
at Deadlock$Friend.bow(Deadlock.java:16)
- locked <0x00000007ab134060> (a Deadlock$Friend)
at Deadlock$2.run(Deadlock.java:34)
at java.lang.Thread.run(Unknown Source)
”Thread-0”:
at Deadlock$Friend.bowBack(Deadlock.java:19)
- waiting to lock <0x00000007ab134060> (a Deadlock$Friend)
at Deadlock$Friend.bow(Deadlock.java:16)
- locked <0x00000007ab134018> (a Deadlock$Friend)
at Deadlock$1.run(Deadlock.java:31)
at java.lang.Thread.run(Unknown Source)

Found 1 deadlock.

从上述输出的信息中可以看出死锁的信息~ 

转载自:https://my.oschina.net/wangmengjun/blog/865125

### jstack 的使用教程与线程分析方法 `jstack` 是 Java 提供的一个命令行工具,用于生成 Java 虚拟机当前线程的堆栈跟踪信息,帮助开发者诊断线程相关的问题,例如死锁、线程阻塞、CPU 占用过高等[^1]。通过 `jstack` 可以获取线程快照,分析线程状态及其持有的资源,从而快速定位问题根源。 #### 命令格式与常用参数 `jstack` 的基本命令格式如下: ```bash jstack [options] <pid> ``` 其中,`<pid>` 表示目标 Java 进程的进程 ID(PID),可以通过 `jps` 命令获取。`options` 是可选参数,用于控制输出格式和其他行为[^2]。 常用选项包括: - **`-l`**:显示额外的锁信息,包括线程当前持有的锁和等待的锁。 - **`-F`**:强制生成线程快照,适用于 JVM 无响应或挂起的情况。 - **`-m`**:混合模式输出,同时显示 Java 方法栈和本地方法栈(Native Stack)。 - **`-h` 或 `-help`**:显示帮助信息[^3]。 例如,使用 `-l` 参数可以获取更详细的锁信息,有助于分析死锁问题: ```bash jstack -l <pid> ``` 若 JVM 无响应,可使用 `-F` 参数强制生成线程快照: ```bash jstack -F -l <pid> ``` #### 线程状态与死锁识别 在 `jstack` 的输出中,线程状态是分析问题的重要线索。常见的线程状态包括: - **RUNNABLE**:线程正在运行或等待 CPU 资源。 - **BLOCKED**:线程因无法获取锁而阻塞,通常发生在使用 `synchronized` 关键字时。 - **WAITING / TIMED_WAITING**:线程处于等待状态,例如调用了 `Object.wait()`、`Thread.sleep()` 等方法。 死锁通常表现为多个线程相互等待对方持有的资源。例如: ```text "Thread-1" #11 prio=5 os_prio=0 tid=0x00007f8c4c0d8800 nid=0x5d03 waiting for monitor entry [0x00007f8c473f6000] java.lang.Thread.State: BLOCKED (on object monitor) at com.example.DeadlockExample.method2(DeadlockExample.java:40) - waiting to lock <0x00000007d6aa2c98> - locked <0x00000007d6aa2ca8> "Thread-0" #10 prio=5 os_prio=0 tid=0x00007f8c4c0d7800 nid=0x5d02 waiting for monitor entry [0x00007f8c474f7000] java.lang.Thread.State: BLOCKED (on object monitor) at com.example.DeadlockExample.method1(DeadlockExample.java:27) - waiting to lock <0x00000007d6aa2ca8> - locked <0x00000007d6aa2c98> ``` 上述输出中,`Thread-1` 正在等待 `<0x00000007d6aa2c98>`,但已持有 `<0x00000007d6aa2ca8>`;而 `Thread-0` 正在等待 `<0x00000007d6aa2ca8>`,但已持有 `<0x00000007d6aa2c98>`。两者形成循环依赖,构成典型的死锁场景。 #### 实际诊断步骤 1. 使用 `jps` 命令查找目标 Java 进程的 PID。 2. 执行 `jstack -l <pid>` 命令生成线程快照。 3. 在输出中查找 `BLOCKED` 状态的线程。 4. 分析线程堆栈信息,识别锁的持有与等待关系。 5. 确认是否存在多个线程相互等待资源,形成循环依赖。 #### 示例代码:死锁模拟 以下是一个简单的死锁模拟代码: ```java public class DeadlockExample { private static final Object lock1 = new Object(); private static final Object lock2 = new Object(); public static void method1() { synchronized (lock1) { System.out.println("Thread 1: Holding lock 1..."); try { Thread.sleep(100); } catch (InterruptedException e) {} System.out.println("Thread 1: Waiting for lock 2..."); synchronized (lock2) { System.out.println("Thread 1: Acquired lock 2."); } } } public static void method2() { synchronized (lock2) { System.out.println("Thread 2: Holding lock 2..."); try { Thread.sleep(100); } catch (InterruptedException e) {} System.out.println("Thread 2: Waiting for lock 1..."); synchronized (lock1) { System.out.println("Thread 2: Acquired lock 1."); } } } public static void main(String[] args) { new Thread(DeadlockExample::method1, "Thread-1").start(); new Thread(DeadlockExample::method2, "Thread-2").start(); } } ``` 运行此程序后,使用 `jstack` 可观察到线程处于 `BLOCKED` 状态,并形成死锁关系。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值