目录

1、jstack-查找死锁

2、jstack找出占用cpu最高的线程堆栈信息


jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。

1、jstack-查找死锁

用jstack加进程id查找死锁,见如下示例

public class DeadLockTest {
    private static Object lock1 = new Object();
    private static Object lock2 = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (lock1) {
                try {
                    System.out.println("thread1 begin");
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
                synchronized (lock2) {
                    System.out.println("thread1 end");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (lock2) {
                try {
                    System.out.println("thread2 begin");
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
                synchronized (lock1) {
                    System.out.println("thread2 end");
                }
            }
        }).start();

        System.out.println("main thread end");
    }
}

// jstack id

  • "Thread-1" 线程名
  • prio=5 优先级=5
  • tid=0x000000002a4be800 线程id
  • nid=0x10f4 线程对应的本地线程标识nid(十六进制)
  • java.lang.Thread.State: BLOCKED 线程状态

还可以用jvisualvm自动检测死锁

2、jstack找出占用cpu最高的线程堆栈信息

测试代码:

public class Math {

    public static final int initData = 666;

    public int compute() {
        int a = 1;
        int b = 2;
        int c = (a + b) * 10;
        return c;
    }

    public static void main(String[] args) {
        Math math = new Math();
        while (true){
            math.compute(); //不停循环计算
        }
    }
}

编译成字节码后,使用java命令执行,注意:代码中不能有中文,也不能指定包名

解决:Error: Could not find or load main class xxx

//解决问题思路:

1、使用命令top  / top -p pid ,显示你的java进程的内存情况,pid是你的java进程号,比如19663

2、按H(大写),获取每个线程的内存情况

3、找到内存和cpu占用最高的线程tid,比如19664

4、转为十六进制得到 0x4cd0,此为线程id的十六进制表示

5、执行 jstack 19663 | grep -A 10 4cd0,得到线程堆栈信息中 4cd0 这个线程所在行的后面10行,从堆栈中可以发现导致cpu飙高的调用方法

6、查看对应的堆栈信息找出可能存在问题的代码

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐