jstack(Java Stack Trace)簡介
jstack:Java進程中線程的堆棧信息跟蹤工具。
功能簡介
??jstack常用來打印Java進程/core文件/遠程調試端口的Java線程堆棧跟蹤信息,包含當前虛擬機中所有線程正在執(zhí)行的方法堆棧信息的集合。
??主要用來定位線程出現(xiàn)長時間停頓的原因,如線程間死鎖、死循環(huán)、請求外部資源導致的長時間等待。
命令格式
jstack [ options ] pid //Java進程
jstack [ options ] executable core //core文件
jstack [ options ] [ server-id@ ] remote-hostname-or-IP //遠程調試端口
其中options選項可有
選項 | 作用 |
---|---|
-F | 當正常輸出的請求不被響應時,強制輸出線程堆棧 |
-l | 除了堆棧外,顯示關于鎖的附加信息 |
-m | 如果調用到本地方法的話,可以顯示C/C++的堆棧信息 |
其他說明
1、When the specified process is running on a 64-bit Java Virtual Machine, you might need to specify the -J-d64 option, for example: jstack -J-d64 -m pid.
2、In mixed mode stack trace, the -m option does not work with the remote debug server.
3、In Windows Systems where the dbgeng.dll file is not present, Debugging Tools For Windows must be installed so these tools work.
輸出格式
jstack的輸出是該進程下的所有線程的堆棧集合,下面是一個線程的堆棧快照信息:
catalina-exec-72" daemon prio=5 tid=114 WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
Local Variable: java.util.concurrent.locks.AbstractQueuedSynchronizer$Node#294
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104)
at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
Local Variable: java.util.concurrent.ThreadPoolExecutor$Worker#50
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
Local Variable: org.apache.tomcat.util.threads.TaskThread$WrappingRunnable#38
at java.lang.Thread.run(Thread.java:745)
屬性 | 說明 |
---|---|
catalina-exec-72 | 線程名稱 |
prio | 該線程JVM中的優(yōu)先級 |
os_prio | 該線程在OS中的優(yōu)先級 |
tid | JVM內的thread id (Java-level thread ID) |
daemon | 表明這個線程是一個守護線程 |
nid | Native thread ID,本地操作系統(tǒng)相關的線程id |
nid說明
This ID is highly platform dependent. It's the nid in jstack thread dumps.
On Windows, it's simply the OS-level thread ID within a process.
On Linux, it's the pid of the thread (which in turn is a light-weight process).
On Solaris, it's the thread as returned by thr_self().
On Mac OS X, it is said to be the native pthread_t value.
狀?態(tài)
在jstack輸出的第二行為線程的狀態(tài),在JVM中線程狀態(tài)使用枚舉 java.lang.Thread.State 來表示,State的定義如下:
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
線程圖
線程狀態(tài) | 說明 |
---|---|
NEW | 當線程對象創(chuàng)建時存在的狀態(tài),此時線程不可能執(zhí)行; |
RUNNABLE | 當調用thread.start()后,線程變成為Runnable狀態(tài)。只要得到CPU,就可以執(zhí)行; |
RUNNING | 線程正在執(zhí)行; |
WAITING | 執(zhí)行thread.join()或在鎖對象調用obj.wait()等情況就會進該狀態(tài),表明線程正處于等待某個資源或條件發(fā)生來喚醒自己; |
TIMED_WAITING | 執(zhí)行Thread.sleep(long)、thread.join(long)或obj.wait(long)等就會進該狀態(tài),與Waiting的區(qū)別在于Timed_Waiting的等待有時間限制; |
BLOCKED | 如果進入同步方法或同步代碼塊,沒有獲取到鎖,則會進入該狀態(tài); |
DEAD | 線程執(zhí)行完畢,或者拋出了未捕獲的異常之后,會進入dead狀態(tài),表示該線程結束。 |
jstack日志關鍵字 | 說 明 |
---|---|
deadlock | 死鎖 |
Waiting on condition | 等待某個資源或條件發(fā)生來喚醒自己。具體需要結合jstacktrace來分析,比如線程正在sleep,網絡讀寫繁忙而等待 |
Blocked | 阻塞 |
waiting on monitor entry | 在等待獲取鎖 |
in Object.wait() | 獲取鎖后又執(zhí)行obj.wait()放棄鎖 |
==如果說系統(tǒng)慢,那么要特別關注Blocked,Waiting on condition==
==如果說系統(tǒng)的cpu耗的高,那么肯定是線程執(zhí)行有死循環(huán),那么此時要關注下Runable狀態(tài)。==
- 死鎖
public class DeadLock {
public static void main(String[] args) throws InterruptedException {
Object obj1 = new Object();
Object obj2 = new Object();
Object obj3 = new Object();
Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
t1.start();
Thread.sleep(5000);
t2.start();
Thread.sleep(5000);
t3.start();
}
}
class SyncThread implements Runnable {
private Object obj1;
private Object obj2;
public SyncThread(Object o1, Object o2) {
this.obj1 = o1;
this.obj2 = o2;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " acquiring lock on " + obj1);
synchronized (obj1) {
System.out.println(name + " acquired lock on " + obj1);
work();
System.out.println(name + " acquiring lock on " + obj2);
synchronized (obj2) {
System.out.println(name + " acquired lock on " + obj2);
work();
}
System.out.println(name + " released lock on " + obj2);
}
System.out.println(name + " released lock on " + obj1);
System.out.println(name + " finished execution.");
}
private void work() {
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Found one Java-level deadlock:
=============================
"t3":
waiting to lock monitor 0x000000000d8fb0a8 (object 0x00000007d7cd4828, a java.lang.Object),
which is held by "t1"
"t1":
waiting to lock monitor 0x000000000560c918 (object 0x00000007d7cd4fa0, a java.lang.Object),
which is held by "t2"
"t2":
waiting to lock monitor 0x000000000560de68 (object 0x00000007d7cd4818, a java.lang.Object),
which is held by "t3"
Java stack information for the threads listed above:
===================================================
"t3":
at com.tzx.test.SyncThread.run(DeadLock.java:41)
- waiting to lock <0x00000007d7cd4828> (a java.lang.Object)
- locked <0x00000007d7cd4818> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:744)
"t1":
at com.tzx.test.SyncThread.run(DeadLock.java:41)
- waiting to lock <0x00000007d7cd4fa0> (a java.lang.Object)
- locked <0x00000007d7cd4828> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:744)
"t2":
at com.tzx.test.SyncThread.run(DeadLock.java:41)
- waiting to lock <0x00000007d7cd4818> (a java.lang.Object)
- locked <0x00000007d7cd4fa0> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:744)
- block范例
public class Blocked {
public static void main(String[] args) {
final Thread thread = new Thread() {
@Override
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(60);
} catch (Exception e) {
}
}
}
};
thread.start();
thread.setName("thread1");
synchronized (thread) {
System.out.println(Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(60);
} catch (Exception e) {
}
}
}
}
2017-11-24 18:39:59
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.51-b03 mixed mode):
"RMI TCP Connection(2)-172.18.95.100" daemon prio=6 tid=0x000000000f958000 nid=0x2598 runnable [0x00000000109ce000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
- locked <0x00000007d6695110> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:538)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Locked ownable synchronizers:
- <0x00000007d62075b0> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"JMX server connection timeout 14" daemon prio=6 tid=0x000000000fbe4000 nid=0x32f8 in Object.wait() [0x00000000105cf000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007d62dbc78> (a [I)
at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
- locked <0x00000007d62dbc78> (a [I)
at java.lang.Thread.run(Thread.java:744)
Locked ownable synchronizers:
- None
"RMI Scheduler(0)" daemon prio=6 tid=0x000000000fbe3000 nid=0xcc0 waiting on condition [0x00000000104cf000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000007d61806c0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1090)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Locked ownable synchronizers:
- None
"RMI TCP Connection(1)-172.18.95.100" daemon prio=6 tid=0x000000000fbe9000 nid=0x3b9c runnable [0x00000000103ce000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read(BufferedInputStream.java:254)
- locked <0x00000007d62a64d0> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:538)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Locked ownable synchronizers:
- <0x00000007d6203998> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"RMI TCP Accept-0" daemon prio=6 tid=0x000000000fbe6000 nid=0x38c0 runnable [0x00000000101be000]
java.lang.Thread.State: RUNNABLE
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:198)
- locked <0x00000007d6181e30> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:530)
at java.net.ServerSocket.accept(ServerSocket.java:498)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:388)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:360)
at java.lang.Thread.run(Thread.java:744)
Locked ownable synchronizers:
- None
"thread1" prio=6 tid=0x000000000f339000 nid=0x2728 waiting for monitor entry [0x000000000f89f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.tzx.test.Blocked$1.run(Blocked.java:12)
- waiting to lock <0x00000007d5d2a758> (a com.tzx.test.Blocked$1)
Locked ownable synchronizers:
- None
"Service Thread" daemon prio=6 tid=0x000000000da67000 nid=0x2de4 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread1" daemon prio=10 tid=0x000000000da63800 nid=0x2ccc waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" daemon prio=10 tid=0x000000000da54800 nid=0x1aec waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Attach Listener" daemon prio=10 tid=0x000000000da54000 nid=0x39fc waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" daemon prio=10 tid=0x00000000056de800 nid=0x3bac runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" daemon prio=8 tid=0x00000000056ce000 nid=0x778 in Object.wait() [0x000000000ed9f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007d5c05568> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000007d5c05568> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)
Locked ownable synchronizers:
- None
"Reference Handler" daemon prio=10 tid=0x000000000da14000 nid=0x1254 in Object.wait() [0x000000000ec9f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007d5c050f0> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x00000007d5c050f0> (a java.lang.ref.Reference$Lock)
Locked ownable synchronizers:
- None
"main" prio=6 tid=0x00000000055e6000 nid=0x2da8 waiting on condition [0x000000000558f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:360)
at com.tzx.test.Blocked.main(Blocked.java:27)
- locked <0x00000007d5d2a758> (a com.tzx.test.Blocked$1)
Locked ownable synchronizers:
- None
"VM Thread" prio=10 tid=0x000000000da12000 nid=0x3434 runnable
"GC task thread#0 (ParallelGC)" prio=6 tid=0x00000000055fc000 nid=0x2da4 runnable
"GC task thread#1 (ParallelGC)" prio=6 tid=0x00000000055fe000 nid=0x10fc runnable
"GC task thread#2 (ParallelGC)" prio=6 tid=0x00000000055ff800 nid=0x32b0 runnable
"GC task thread#3 (ParallelGC)" prio=6 tid=0x0000000005602800 nid=0x534 runnable
"VM Periodic Task Thread" prio=10 tid=0x000000000f2b0800 nid=0x2f78 waiting on condition