内存监控工具——jstack
一、jstack作用
Jstack是Jdk自带的线程跟踪工具,用于打印指定Java进程的线程堆栈信息。
二、语法
jstack [option] < pid >
说明:
option:命令选项,常用选项如下:
- -F:当’jstack [-l] pid’没有相应的时候强制打印栈信息,如果直接jstack无响应时,用于强制jstack),一般情况不需要使用
- -l:长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表,会使得JVM停顿得长久得多(可能会差很多倍,比如普通的jstack可能几毫秒和一次GC没区别,加了-l 就是近一秒的时间),-l 建议不要用。一般情况不需要使用
- -m:打印java和native c/c++框架的所有栈信息.可以打印JVM的堆栈,显示上Native的栈帧,一般应用排查不需要使用
- pid:进程id
三、举例
1、运行如下代码:
public class Test {
public static void main(String[] args) {
while(true) {
}
}
}
2、执行jps命令获取进程id:
3、执行jstack pid命令:查看pid进程内线程信息:
C:\Users\99273>jstack 14980
2019-07-22 00:59:34
Full thread dump Java HotSpot(TM) Client VM (25.131-b11 mixed mode):
//– daemon:线程是否是守护线程
"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x15939400 nid=0x104 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
//prio表示线程优先级
"C1 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x1590a400 nid=0x10f4 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
//os_prio表示该线程对应的操作系统线程的优先级 tid表示Java中线程编号
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x158e5c00 nid=0x3dac waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
//nid:即native id,该线程对应的操作系统中本地线程编号,每一个java线程都有一个对应的操作系统线程。
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x158e4c00 nid=0x2d48 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
//"Finalizer"为线程名
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x158c8c00 nid=0x1d7c in Object.wait() [0x15b8f000]
//表示java.lang.Thread.State线程状态,稍后详细讲解。
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x05407ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x05407ee0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x158b3400 nid=0x964 in Object.wait() [0x15aff000]
//WAITING (on object monitor)表示该线程处于等待状态,括号中的内容说明了导致等待的原因。
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x05405f68> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x05405f68> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"main" #1 prio=5 os_prio=0 tid=0x014bc400 nid=0x2d34 runnable [0x0156f000]
java.lang.Thread.State: RUNNABLE
at com.Test.main(Test.java:5)
"VM Thread" os_prio=2 tid=0x0324c400 nid=0x3d94 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x15996000 nid=0x9a8 waiting on condition
JNI global references: 6
说明:(上述代码中有对应注解内容)
– daemon:线程是否是守护线程
– prio:线程优先级
– tid:Java中线程编号
– os_prio:该线程对应的操作系统线程的优先级
– nid:即native id,该线程对应的操作系统中本地线程编号,每一个java线程都有一个对应的操作系统线程。
– "Finalizer"指线程名
– 下一行中的java.lang.Thread.State:指线程状态
– WAITING (on object monitor):表示该线程处于等待状态,括号中的内容说明了导致等待的原因。
四、线程与Monitor
- 进入区(Entrt Set):表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则迚入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。
- 拥有者(The Owner):表示某一线程成功竞争到对象锁。
- 等待区(Wait Set) :表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。
说明:
一个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程为“Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在“Wait Set”中等待的线程状态是 “in Object.wait()”。 被 synchronized保护起来的代码段称为临界区,当一个线程申请进入临界区时,它就进入了 “Entry Set”队列。
五、线程状态:
- NEW:线程刚刚被创建,也就是已经new过了,但是还没有调用start()方法,jstack命令不会列出处于此状态的线程信息。
- RUNNABLE:RUNNABLE这个名字很具有欺骗性,很容易让人误以为处于这个状态的线程正在运行;事实上,这个状态只是表示,线程是可运行的。一个单核CPU在同一时刻,只能运行一个线程。
- BLOCKED:线程处于阻塞状态,正在等待一个监视器锁(monitor lock)。通常情况下,是因为本线程与其他线程公用了一个锁。其他在线程正在使用这个锁进入某个synchronized同步方法块或者方法,而本线程进入这个同步代码块也需要这个锁,最终导致本线程处于阻塞状态,例子:程序文件夹——>《BLOCKED.docx》文档;
- WAITING:等待状态,等待某个condition或monitor发生,调用以下方法可能会导致一个线程处于等待状态:
wait() 不指定超时时间,
join() 不指定超时时间,
park() - TIMED_WAITING:线程等待指定的时间,对于以下方法的调用,可能会导致线程处于这个状态:
wait(long timeout) 指定超时时间,
join(long millis) 指定超时时间,
sleep(long millis) 指定超时时间,
parkNanos(long nanos)
parkUntil(long deadline) - TERMINATED:线程终止。