java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java jstack

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

作者:242030

jstack(stack trace for java)是java虚拟机自带的一种堆栈跟踪工具,主要用于生成java虚拟机当前时刻的线程快照,下面我们就来学习一下它的具体使用吧

1、jstack介绍

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

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

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

jstack主要分为两个功能:

当指定的进程在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命

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

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

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的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文