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

标签:java,jstack,工具
0
投稿

猜你喜欢

  • Java设计模式之接口隔离原则精解

    2022-05-05 16:42:05
  • Android中选项菜单(OptionMenu)的创建方法

    2021-06-08 14:14:42
  • Android ActionBarActivity设置全屏无标题的方法总结

    2023-01-23 04:49:37
  • Android开发之android_gps定位服务简单实现

    2023-07-31 20:02:25
  • 解析使用enumerator模式简化异步操作的详解

    2021-10-08 01:44:54
  • Java实现合并两个有序序列算法示例

    2021-09-06 23:23:53
  • java开发AOP面向切面编程入门

    2021-08-22 04:47:56
  • 一篇文章带你入门Java基本概念

    2023-11-26 01:17:08
  • Android实现歌词滚动效果

    2023-11-08 04:29:54
  • 基于Java实现经典蜘蛛纸牌游戏

    2021-09-06 15:22:57
  • Android开发RecyclerView实现折线图效果

    2022-08-27 12:59:34
  • android自定义进度条渐变圆形

    2022-07-15 02:04:14
  • MVVM和MVVMLight框架介绍及在项目中的使用详解

    2021-07-29 06:59:10
  • Java基于对象流实现银行系统

    2023-09-10 02:54:21
  • java.lang.NoClassDefFoundError错误解决办法

    2021-12-29 03:52:27
  • C#集合查询Linq在项目中使用详解

    2022-09-16 13:50:09
  • C语言malloc分配问题详解

    2023-07-22 05:10:34
  • spring boot 集成 shiro 自定义密码验证 自定义freemarker标签根据权限渲染不同页面(推荐

    2023-07-28 17:39:16
  • C#生成防伪码的思路及源码分享

    2022-10-27 03:53:41
  • 50 道Java 线程面试题(经典)

    2023-11-23 19:47:37
  • asp之家 软件编程 m.aspxhome.com