java堆栈跟踪工具jstack的使用教程

 更新时间:2023年11月14日 08:41:25   作者:242030  
jstack(stack trace for java)是java虚拟机自带的一种堆栈跟踪工具,主要用于生成java虚拟机当前时刻的线程快照,下面我们就来学习一下它的具体使用吧

1、jstack介绍

jstack(stack trace for java)是java虚拟机自带的一种堆栈跟踪工具。

jstack主要用于生成java虚拟机当前时刻的线程快照,线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。

线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。

jstack主要分为两个功能:

  • 针对活着的进程做本地的或远程的线程dump
  • 针对core文件做线程dump

当指定的进程在64位Java虚拟机上运行时,可能需要指定-J-d64选项,例如:jstack -J-d64 -m pid。

2、线程状态

线程通常有下面5中状态:

1、新建状态(New): 新创建了一个线程对象。

2、就绪状态(Runnable) :线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。

3、运行状态(Running): 就绪状态的线程获取了CPU,执行程序代码。

4、阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。

同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。

当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

关于线程状态,具体也可以查看:java.lang.Thread.State类。

想要通过jstack命令来分析线程的情况的话,首先要知道线程都有哪些状态,下面这些状态是我们使用jstack命

令查看线程堆栈信息时可能会看到的线程的几种状态:

  • RUNNABLE,线程运行中或I/O等待
  • BLOCKED,线程被阻塞,在等待monitor锁(synchronized关键字)
  • TIMED_WAITING ,线程在等待唤醒,但设置了时限
  • WAITING ,线程在无限等待唤醒

在线程的堆栈中,需要特别留意以下几种状态:

  • Deadlock: 死锁(重点关注)
  • Waiting on condition: 等待资源(重点关注)
  • Waiting on monitor entry : 等待获取监视器(重点关注)
  • Blocked :阻塞(重点关注)
  • Runnable :执行中
  • Suspended : 暂停
  • Object.wait()或TIME_WAITING :对象等待中
  • Parked : 停止

3、jstack命令格式

jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP

pid:Java进程的ID,可以通过jps命令查询到。

executable: 产生core dump的Java可执行程序。

core:要打印的堆栈跟踪的核心文件。

server-id:当多个DEBUG服务器在同一远程主机上运行时,可使用的可选唯一ID。

remote-hostname-or-IP:远程DEBUG的服务器主机名或IP地址。

pid: 需要被打印配置信息的java进程id,可以用jps查询。

常用参数说明:

-F:当 jstack [-l] pid 没有响应时,强制打印一个堆栈转储。

-l:打印关于锁的其他信息,比如拥有的java.util.concurrent ownable同步器的列表,会使得JVM停顿得长久得多。

-m:打印包含Java和本机C/ C++帧的混合模式堆栈跟踪。

-h:打印帮助信息。

-help:打印帮助信息。

3.1 jstack pid

第一行各个单词的解析,

daemon:线程名称 。

prio:线程优先级

tid:指Java Thread id。

nid:指native线程的id。。

[0x000000002369e000]:线程栈起始地址。

3.2 死循环

package com.example.controller;

public class Test2 {

    public static void main(String[] args) {
        while (true) {
        }
    }
    
}

3.3 Object.wait()情况

package com.example.controller;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test3 {
    static class TestTask implements Runnable {
        @Override
        public void run() {
            synchronized (this) {
                try {
                    //等待被唤醒
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService ex = Executors.newFixedThreadPool(1);
        ex.execute(new TestTask());
    }
}

3.4 死锁情况

package com.example.controller;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test4 {

    public static void main(String[] args) {
        Object obj1 = new Object();
        Object obj2 = new Object();
        ExecutorService ex = Executors.newFixedThreadPool(2);
        // 起10个线程
        for (int i = 0; i < 10; i++) {
            int order = i % 2 == 0 ? 1 : 0;
            ex.execute(new TestTask(order, obj1, obj2));
        }
    }

    static class TestTask implements Runnable {
        private Object obj1;
        private Object obj2;
        private int order;

        public TestTask(int order, Object obj1, Object obj2) {
            this.order = order;
            this.obj1 = obj1;
            this.obj2 = obj2;
        }

        public void test1() throws InterruptedException {
            synchronized (obj1) {
                synchronized (obj2) {
                    System.out.println("test。。。");
                }
            }
        }

        public void test2() throws InterruptedException {
            synchronized (obj2) {
                synchronized (obj1) {
                    System.out.println("test。。。");
                }
            }
        }

        @Override
        public void run() {
            while (true) {
                try {
                    if (this.order == 1) {
                        this.test1();
                    } else {
                        this.test2();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.5 等待io

package com.example.controller;

import java.io.IOException;
import java.io.InputStream;

public class Test5 {

    public static void main(String[] args) throws IOException {
        InputStream is = System.in;
        int i = is.read();
        System.out.println("exit。");
    }

}

以上就是java堆栈跟踪工具jstack的使用教程的详细内容,更多关于java jstack的资料请关注脚本之家其它相关文章!

相关文章

  • java多线程之Future和FutureTask使用实例

    java多线程之Future和FutureTask使用实例

    这篇文章主要介绍了java多线程之Future和FutureTask使用实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • 使用Java实现一个能保留计算过程的计算器

    使用Java实现一个能保留计算过程的计算器

    计算器是我们日常生活中常用的工具之一,它能够进行基本的数学运算,如加法、减法、乘法和除法,而在设计一个计算器时,我们可以通过使用Java编程语言来实现一个简单的控制台计算器,并且让它能够保留计算过程,文中有详细的代码示例,需要的朋友可以参考下
    2023-11-11
  • Java枚举之EnumSet详解

    Java枚举之EnumSet详解

    这篇文章主要介绍了Java枚举之EnumSet详解,使用时进行与或运算,但是定义多了之后,会很乱、臃肿,编写容易出错,EnumSet可以实现类似的功能,且使用起来很简洁,需要的朋友可以参考下
    2023-12-12
  • SpringBoot配置文件加载方法详细讲解

    SpringBoot配置文件加载方法详细讲解

    springboot默认读取的配置文件名字是:“application.properties”和“application.yml”,默认读取四个位置的文件:根目录下、根目录的config目录下、classpath目录下、classpath目录里的config目录下
    2022-10-10
  • Mybatis如何根据List批量查询List结果

    Mybatis如何根据List批量查询List结果

    这篇文章主要介绍了Mybatis如何根据List批量查询List结果,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Spring的Bean容器介绍

    Spring的Bean容器介绍

    今天小编就为大家分享一篇关于Spring的Bean容器介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • 深入解析Java编程中final关键字的作用

    深入解析Java编程中final关键字的作用

    final关键字正如其字面意思一样,意味着最后,比如被final修饰后类不能集成、变量不能被再赋值等,以下我们就来深入解析Java编程中final关键字的作用:
    2016-06-06
  • JAVA位运算的知识点总结

    JAVA位运算的知识点总结

    在本篇文章里小编给大家整理的是关于JAVA有关位运算的全套梳理,需要的朋友们可以参考学习下。
    2020-03-03
  • 基于java中cookie和session的比较

    基于java中cookie和session的比较

    下面小编就为大家带来一篇基于java中cookie和session的比较。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • 你知道JVM中GC Root对象有哪些吗

    你知道JVM中GC Root对象有哪些吗

    这篇文章主要介绍了你知道JVM中GC Root对象有哪些,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01

最新评论