Java中工具Jstack的使用实例
作者:Mr_Yao 发布时间:2023-07-26 15:18:02
jstack - Prints Java thread stack traces for a Java process, core file, or remote debug server.
Jstack 主要的作用是生成当前进程中所有线程的信息,也就是当前时刻 JVM 的线程快照,通过线程的信息我们可以定位到程序中出现长时间停顿、CPU 占用率过高等问题。
线程快照中的信息是当前 java 虚拟机内每一条线程正在执行的方法的堆栈集合,有了堆栈信息我们就可以分析出我们的程序问题出现在那,比如线程间死锁、外部资源请求时间过长、死循环等。
使用:
jstack [ options ] pid
jstack [ options ] executable core
jstack [ options ] [ server-id@ ] remote-hostname-or-IP
OPTIONS
-F
Force a stack dump when jstack [-l] pid does not respond.
-l
Long listing. Prints additional information about locks such as a list of owned java.util.concurrent ownable synchronizers. See the
AbstractOwnableSynchronizer class description at
http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/AbstractOwnableSynchronizer.html
-m
Prints a mixed mode stack trace that has both Java and native C/C++ frames.
-F 当正常的请求不被响应时,强制输出堆栈信息。
-l 额外打印锁的信息,当发生死锁是可以查看锁的信息
-m 如果调用本地方法栈的信息,可以打印 C/C++的堆栈
以一个发生死锁的例子来看一下使用 Jstack 查看到的信息
public class Jstack {
private static Object obj1 = new Object();
private static Object obj2 = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (obj1) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2) {
}
}
}).start();
new Thread(() -> {
synchronized (obj2) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj1) {
}
}
}).start();
}
}
上面代码中,第一个线程拿到 obj1 的锁,等待 obj2 的锁,第二个线程拿到 obj2 的锁,等待 obj1 的锁,这样就会发生死锁。
先通过jps命令获取到先拿到当前的进程 pid,然后通过 jstack 获取线程的信息。可以看到有两个线程都处于阻塞状态。
"Thread-1" #12 prio=5 os_prio=0 tid=0x00007fdff871c800 nid=0x3cc2 waiting for monitor entry [0x00007fdfce0fc000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.demo.jstack.Jstack.lambda$main$1(Jstack.java:36)
- waiting to lock <0x000000076e925a90> (a java.lang.Object)
- locked <0x000000076e925aa0> (a java.lang.Object)
at com.example.demo.jstack.Jstack$$Lambda$2/2052001577.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0" #11 prio=5 os_prio=0 tid=0x00007fdff871a800 nid=0x3cc1 waiting for monitor entry [0x00007fdfce1fc000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.demo.jstack.Jstack.lambda$main$0(Jstack.java:25)
- waiting to lock <0x000000076e925aa0> (a java.lang.Object)
- locked <0x000000076e925a90> (a java.lang.Object)
at com.example.demo.jstack.Jstack$$Lambda$1/1174361318.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
第一行显示可线程名、线程优先级、线程 id、线程状态描述等信息
第二行显示的是当前线程的状态
Java 中线程的状态分为 NEW、RUNNABLE、BLOCKED、WATING、TIMED_WATING、TERMINATED,但是在快照中 NEW 状态是不会出现的。
再下面的就是当前线程的调用栈的信息。调用栈中包含了锁的信息。
locked 表示使用 synchronized 申请对象锁成功,监视器的拥有者
waiting to lock 表示使用 synchronized 申请对象锁未成功,进入等待区。
waiting on 表示用 synchronized 申请对象锁成功后,调用了 wait 方法,进入对象的等待区等待。
parking to wait for park 是基本的线程阻塞原语,不通过监视器在对象上阻塞。随 concurrent 包会出现的新的机制,与 synchronized 体系不同。
在最后也显示出了代码中出现死锁的信息
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007fdfac006638 (object 0x000000076e925a90, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00007fdfac003da8 (object 0x000000076e925aa0, a java.lang.Object),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.example.demo.jstack.Jstack.lambda$main$1(Jstack.java:36)
- waiting to lock <0x000000076e925a90> (a java.lang.Object)
- locked <0x000000076e925aa0> (a java.lang.Object)
at com.example.demo.jstack.Jstack$$Lambda$2/2052001577.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at com.example.demo.jstack.Jstack.lambda$main$0(Jstack.java:25)
- waiting to lock <0x000000076e925aa0> (a java.lang.Object)
- locked <0x000000076e925a90> (a java.lang.Object)
at com.example.demo.jstack.Jstack$$Lambda$1/1174361318.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
来源:https://juejin.cn/post/7091212605330554911


猜你喜欢
- 缘起随着 App 的成长,我们难免会遇到以下这些需求:H5 跳原生界面Notification 点击调相关界面根据后台返回数据跳转界面,例如
- 1、使用AsyncTask异步任务实现,调用publishProgress()方法刷新进度来实现(已优化)public class MyAs
- 本文实例为大家分享了Java实现UDP多线程在线咨询,供大家参考,具体内容如下1.发送的线程import java.io.BufferedR
- public static void main(String[] args) { System.out
- 本文实例讲述了Android实现学生管理系统,分享给大家供大家参考。具体如下:(1)管理系统实现的功能主要是:学生、教师的注册登录,和选课,
- 一、什么是状态模式定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。主要解决:当控制一个对象状态的条件表达式过于
- (注意:本文基于JDK1.8)前言增删改查,修改元素,Vector提供了3个方法,包括迭代器中的一个,不过本文只分析Vector自身的两个修
- 虽然说模块通信、路由协议在Android已经不新鲜了,但是如果脱离了那些优秀的开源库我们从零开始自己造一个库,有时候重复造轮子会让自己对所谓
- 在以往的 Tomcat 项目中,一直习惯用 Ant 打包,使用 build.xml 配置,通过 ant -buildfile 的方式在机器上
- 实现效果:Form1.cs代码:using System;using System.Collections.Generic;using Sy
- 1、点击【File】->【Project Structure】菜单(或使用Shift+Ctrl+Alt+S快捷键),打开【Projec
- 一、获取android工程里面的各种资源的id; 1.1 string型 比如下面: << string name=”OK”&g
- Settings是WebView提供给上层App的一个配置Webview的接口,每个WebView都有一个WebSettings,要控制We
- 前言Dagger2作为依赖注入神器,相信很多朋友都听说过它的大名。只不过它的有些概念,理解起来并不是那么清晰,并且在使用的过程中,也比较迷糊
- 本文实例讲述了Android编程实现任务管理器的方法。分享给大家供大家参考,具体如下:任务管理器可以实现的功能有:1.查看当前系统下运行的所
- 一、静态代理模式1.1、 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标
- Lombok有什么用在我们实体Bean中有大量的Getter/Setter方法以及toString, hashCode等可能不会用到,但是某
- Java 使用getClass().getResourceAsStream()方法获取资源之前想获取一个资源文件做一些处理,使用getCla
- 第1类:嵌套模式package day14;import java.io.FileInputStream;import java.io.Fi
- android中提供了4中动画: AlphaAnimation 透明度动画效果 ScaleAnimation 缩放动画效果 Translat