当前位置 : 主页 > 编程语言 > java >

JVM命令之 jstack:打印JVM中线程快照

来源:互联网 收集:自由互联 发布时间:2022-07-05
学习 尚硅谷 宋红康 JVM从入门到精通 的学习笔记 概述 jstack(JVM Stack Trace)是用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪),线程快照就是当前虚拟机内指定进程的每一条

学习 尚硅谷 宋红康 JVM从入门到精通 的学习笔记

概述

jstack(JVM Stack Trace)是用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪),线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合.
生成线程的快照的作用: 多线程在执行过程中可能会出现长时间停顿的问题,线程争抢资源的时候有的线程就需要等待同步监视器或者死锁,或者死循环,等等以上情况都会导致线程不正常的情况, 会出现长时间的停顿,要想知道是哪段代码导致的线程停顿的,这个时候就需要jstack指令了

JVM命令之 jstack:打印JVM中线程快照_linux

JVM命令之 jstack:打印JVM中线程快照_jvm_02

语法

基本语法
option参数:-F
当正常输出的请求不被响应时,强制输出线程堆栈
option参数:-l
除堆栈外,显示关于锁的附加信息
option参数:-m
如果调用本地方法的话,可以显示C/C++的堆栈
option参数:-h
帮助操作

基本语法说明:
JVM命令之 jstack:打印JVM中线程快照_java_03
JVM命令之 jstack:打印JVM中线程快照_java_04
举例如下:
1.JVM命令之 jstack:打印JVM中线程快照_堆栈_05
2.加-l参数:JVM命令之 jstack:打印JVM中线程快照_死锁_06
总结:
如果程序出现等待问题,可以使用该指令去查看问题所在,结果中也会提示你问题所在

演示

死锁问题排查

/**
* 演示线程的死锁问题

*/
public class ThreadDeadLock {

public static void main(String[] args) {

StringBuilder s1 = new StringBuilder();
StringBuilder s2 = new StringBuilder();

new Thread(){
@Override
public void run() {

synchronized (s1){

s1.append("a");
s2.append("1");

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}

synchronized (s2){
s1.append("b");
s2.append("2");

System.out.println(s1);
System.out.println(s2);
}

}

}
}.start();


new Thread(new Runnable() {
@Override
public void run() {
synchronized (s2){

s1.append("c");
s2.append("3");

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}

synchronized (s1){
s1.append("d");
s2.append("4");

System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

new Thread(new Runnable() {
@Override
public void run() {
Map<Thread, StackTraceElement[]> all = Thread.getAllStackTraces();//追踪当前进程中的所有的线程
Set<Map.Entry<Thread, StackTraceElement[]>> entries = all.entrySet();
for(Map.Entry<Thread, StackTraceElement[]> en : entries){
Thread t = en.getKey();
StackTraceElement[] v = en.getValue();
System.out.println("【Thread name is :" + t.getName() + "】");
for(StackTraceElement s : v){
System.out.println("\t" + s.toString());
}
}
}
}).start();
}


}

说明,第一个线程先获取s1锁,再获取s2锁 , 第二个线程先获取s2锁,再获取s1锁,这样就很容易出现死锁了

用命令排查

启动上面的代码

JVM命令之 jstack:打印JVM中线程快照_死锁_07

JVM命令之 jstack:打印JVM中线程快照_死锁_08

这是就打印了线程的相关信息了,

箭头标识的这两个线程出现了阻塞状态,就是因为死锁了,
JVM命令之 jstack:打印JVM中线程快照_死锁_09

然后里面就显示deadlock了.
JVM命令之 jstack:打印JVM中线程快照_死锁_10

线程睡眠问题排查

public class TreadSleepTest {
public static void main(String[] args) {
System.out.println("hello - 1");
try {
Thread.sleep(1000 * 60 * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("hello - 2");
}
}

上面的代码会睡眠10分钟.让代码不执行

用命令排查

启动上面的main方法

JVM命令之 jstack:打印JVM中线程快照_堆栈_11

可以看到main线程是time waiting状态了.
JVM命令之 jstack:打印JVM中线程快照_jvm_12

多线程同步问题

/**
* 演示线程的同步
*/
public class ThreadSyncTest {
public static void main(String[] args) {
Number number = new Number();
Thread t1 = new Thread(number);
Thread t2 = new Thread(number);

t1.setName("线程1");
t2.setName("线程2");

t1.start();
t2.start();
}
}

class Number implements Runnable {
private int number = 1;

@Override
public void run() {
while (true) {
synchronized (this) {

if (number <= 100) {

try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(Thread.currentThread().getName() + ":" + number);
number++;

} else {
break;
}
}
}
}

}

上面代码说明,创建两个Number线程 ,然后去给number变量自增,其中锁对象是this, 这样就是同步

JVM命令之 jstack:打印JVM中线程快照_死锁_13


上一篇:JVM监控及诊断工具-命令行篇
下一篇:没有了
网友评论