jstack的主要作用是生成JVM当前时刻线程的快照(threaddump,即当前进程中所有线程的信息)。可以帮助定位程序中出现的问题,如长时间停顿,CPU占有率过高等问题,也可以看出哪些程序是守护线程,哪些程序是用户线程。

在命令行输出jstack即可看出相关帮助信息:

jstack使用_.net

jstack的基本语法是:jstack [option] <pid>

  • 如果jstack后面加了-l参数,那么就会打印一些关于锁的信息;
  • pid就是进程的id;

这里运行下面这段代码查看线程快照:

package dgb.test.concurrent;

import java.lang.management.ManagementFactory;

/**
* @author Dongguabai
* @date 2018/9/2 19:35
*/
public class SuspendTest {

public static void main(String[] args) throws InterruptedException {
ChangeObjectThread c1 = new ChangeObjectThread("thread-1");
ChangeObjectThread c2 = new ChangeObjectThread("thread-2");

c1.start();
c2.start();
// Thread.sleep(1000);
c1.resume();
c2.resume();
}

public static class ChangeObjectThread extends Thread {
public ChangeObjectThread(String name) {
super(name);
}

@Override
public void run() {
System.out.println("线程【" + getName() + "】正在执行");
Thread.currentThread().suspend();
}
}
}

查看当前进程的PID(通过Java代码查看pid的方法可以参看:​​Java程序中获取当前进程的pid​​,也可以使用 jps 命令)后执行命令:jstack -l <PID>:

C:\Users\Dongguabai>jstack -l 3572
//当前线程快照生成的时间
2018-09-02 20:11:42
//运行的时候的JRE的版本信息,这里是服务器端版本
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.65-b01 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000002a49000 nid=0x4828 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

//这是是刚刚我们创建的线程,pri=5是线程的优先级(默认为5,数字越大优先级越高);
//线程类型:线程分为守护线程 (daemon) 和非守护线程 (non-daemon) 两种,通常都是守护线程;
//如果使用 java.lang.Thread 类生成一个线程的时候,线程名称为 Thread-(数字) 的形式;
//tid是JVM线程的id:JVM内部线程的唯一标识,通过 java.lang.Thread.getId()获取,通常用自增的方式实现;
//nid=0x395c系统线程id:对应的系统线程id(Native Thread ID),可以通过 top 命令进行查看,id是十六进制的形式;结合top H可以快速查看CPU占用过高的线程;
"thread-2" #12 prio=5 os_prio=0 tid=0x0000000019543800 nid=0x395c runnable
//0x000000001a1af000起始栈地址:线程堆栈调用的其实内存地址;
[0x000000001a1af000]
//RUNNABLE实线程的状态;
java.lang.Thread.State: RUNNABLE
//线程的RUNNABLE状态是由这个导致的;
at java.lang.Thread.suspend0(Native Method)
at java.lang.Thread.suspend(Thread.java:1029)
at dgb.test.concurrent.SuspendTest$ChangeObjectThread.run(SuspendTest.java:32)

//由于加了-l参数,所以会出现下面的消息;当前线程是否处于同步块内;
Locked ownable synchronizers:
- None

"thread-1" #11 prio=5 os_prio=0 tid=0x0000000019542800 nid=0xcf0 runnable [0x000000001a0af000]
java.lang.Thread.State: RUNNABLE
at java.lang.Thread.suspend0(Native Method)
at java.lang.Thread.suspend(Thread.java:1029)
at dgb.test.concurrent.SuspendTest$ChangeObjectThread.run(SuspendTest.java:32)

Locked ownable synchronizers:
- None

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x00000000194e6800 nid=0x471c runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x00000000194cb800 nid=0x4b70 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001946d000 nid=0x4508 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000000019469000 nid=0x1438 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x00000000193b2000 nid=0x4274 runnable [0x0000000019aae000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x00000000d650dfa0> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
- locked <0x00000000d650dfa0> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

Locked ownable synchronizers:
- None

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000018bf3800 nid=0xe64 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000017850000 nid=0x4a00 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000002b39800 nid=0xb94 in Object.wait() [0x0000000018bae000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d5f870b8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000000d5f870b8> (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)

Locked ownable synchronizers:
- None

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000017819000 nid=0x3734 in Object.wait() [0x0000000018aaf000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d5f86af8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
- locked <0x00000000d5f86af8> (a java.lang.ref.Reference$Lock)

Locked ownable synchronizers:
- None

"VM Thread" os_prio=2 tid=0x0000000017817800 nid=0x4c8 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002a5e800 nid=0x3860 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002a60000 nid=0x4548 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002a62000 nid=0x45d0 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002a63800 nid=0x2d1c runnable

"VM Periodic Task Thread" os_prio=2 tid=0x000000001959e800 nid=0xaec waiting on condition

JNI global references: 19

也可以使用:

jstack -l 1111 >1.txt

导出到 1.txt 文件。