首页 > 系统相关 >使用jstack排查JVM进程死锁

使用jstack排查JVM进程死锁

时间:2023-04-05 15:33:39浏览次数:50  
标签:java jstack 8200 DeadLockSample 死锁 线程 JVM

前言

在Linux系统使用JDK自带的jstack指令分析输出的线程信息排查死锁的详细步骤。

例子程序

下面是一个模拟线程死锁的例子程序,编译(javac DeadLockSample.java)后执行(java DeadLockSample)这个程序来启动一个JVM进程。

其中一个线程会成功获取到DeadLockSample的Class对象锁持续打印(locking...),由于是死循环,所以锁不会释放,其他两个意图获取锁的线程只能无限等待。

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

public class DeadLockSample {

    private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(3);

    public static void main(String[] args) {
        EXECUTOR.submit(DeadLockSample::doSomething);
        EXECUTOR.submit(DeadLockSample::doSomething);
        EXECUTOR.submit(DeadLockSample::doSomething);
    }

		/**
     * 占用锁循环输出不释放
     */  
    private static synchronized void doSomething() {
        try {
            while (true) {
                System.out.println("locking...");
                TimeUnit.SECONDS.sleep(3);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

排查过程

找出Java进程ID

通过JDK自带的jps指令列出服务器上所有Java进程,找到我们排查死锁的进程ID。

image-20211028102037186

找出等待相同锁的多个线程

执行jstack <Java进程ID>查看进程中所有线程运行信息。

jstack 8200

从输出的信息中我们可以看到有两个线程(线程名为pool-1-thread-2和pool-1-thread-3)在等待(waiting to lock)同一个类型(a java.lang.Class for DeadLockSample)对象(0x00000000f0c72bb8)的锁。

image-20211028102418141

image-20211028102450790

而持有(locked)这个类型(a java.lang.Class for DeadLockSample)对象(0x00000000f0c72bb8)锁的线程名为(pool-1-thread-1)。

到此我们已经找出了持有死锁的线程,关键在于锁肯定被一个线程持有,如果有线程在等待同一把锁,那么他们锁定(lock)和等待(waiting to lock)的对象类型(a java.lang.Class for DeadLockSample)和对象实例的十六进制唯一 标识(0x00000000f0c72bb8)是一样的。

image-20211028102519694

其他快速查找方式

由于jstack输出的信息非常多,查找关键信息不是很方便,通过grep命令过滤只输出我们需要的信息可以更快的定位问题线程,格式为jstack <Java进程ID> | grep '<过滤关键字>'

  • 找出等待锁的相关信息
jstack 8200 | grep 'waiting to lock'

image-20211028104509584

  • 找出所有持有锁的相关信息
jstack 8200 | grep 'locked'

image-20211028104718518

  • 将jstack结果输出到指定文件,格式为jstack [Java进程ID] > [文件名],> 代表覆盖,>> 代表追加。
jstack 8200 > 8200.text
# jstack 8200 >> 8200.text

最后根据十六进制唯一标识在文件中查找相关线程信息也可以定位问题。

总结

排查主要使用jstack命令输出线程运行相关信息,然后找出持有、等待锁的线程,并根据锁的对象实例的十六进制唯一标识来判断是否是通一把锁。

虽然知道了死锁的相关信息,但还需要根据线程名、对象的类型、线程运行状态、方法堆栈等信定位到代码内的具体位置。

其实有更快的方式是使用阿里的 Arthas,如果不方便或者没有这个工具包使用本文方式是比较合适的,因为指令JDK自带无需依赖其他工具。

标签:java,jstack,8200,DeadLockSample,死锁,线程,JVM
From: https://www.cnblogs.com/shuiyao3/p/17289520.html

相关文章

  • 让JVM感知K8s资源限制
    无感知导致的问题当我们在K8s中Deployments配置资源限制和预留的时候,比如设置最大内存为500M。但是宿主机的总内存为8G,这时候Pod启动后会超出内存限制,被Deployments杀掉。但为了维护设置的副本数量又创建新的,如此反复。原因是默认情况JVM默认最大堆空间为系统总内存的1/4,在容器......
  • 如何使用和查找JVM选项
    Java程序启动方式执行类:java[-options]class[args...]执行jar文件:java[-options]-jarjarfile[args...]options指JVM选项,比如堆内存大小;args指程序接收的参数,也就是publicstaticvoidmain(String[]args)中的args。class指启动类文件(.class)的路径,jarfile指......
  • JVM的垃圾收集算法
    介绍分代收集理论和几种垃圾收集算法的思想及其发展过程。分代收集理论当前商业虚拟机的垃圾收集器,大多数都遵循了“分代收集”(GenerationalCollection)的理论进行设计,分代收集名为理论,实质是一套符合大多数程序运行实际情况的经验法则,分代收集理论它建立在两个分代假说之上:弱......
  • JVM的垃圾收集算法
    介绍分代收集理论和几种垃圾收集算法的思想及其发展过程。分代收集理论当前商业虚拟机的垃圾收集器,大多数都遵循了“分代收集”(GenerationalCollection)的理论进行设计,分代收集名为理论,实质是一套符合大多数程序运行实际情况的经验法则,分代收集理论它建立在两个分代假说之上:......
  • freeRTOS任务死锁
    一、freeRTOS任务死锁FreeRTOS任务死锁是一种常见的问题,通常发生在多个任务相互等待对方释放资源的情况下。以下是一个简单的例子,用于说明FreeRTOS任务死锁的情况:假设有两个任务Task1和Task2,它们需要共享两个资源ResourceA和ResourceB。每个任务都需要同时访问这两个资源才能完成它......
  • JVM——JVM级别下的高并发问题
    摘要本文将深入的学习与分析JVM虚拟机的原理和相关的调优的相关实例。JVM级别下的高并发问题Java内存模型与线程“让计算机并发执行若干个运算任务”与“更充分地利用计算机处理器的效能”之间的因果关系,看起来顺理成章,实际上它们之间的关系并没有想象中的那么简单,其中一个重......
  • Address already in use: JVM_Bind:80
    今天maven工程中配置pom.xml时Tomcat配了80端口号,结果提示Addressalreadyinuse:JVM_Bind:80,也就是80端口被占用,于是就按照往常的惯例去查看是什么进程占用了80端口1、打开cmd命令窗口,输入netstat-ano|findstr80,回车就会看见被占用端口号8080所对应的PID为4然后去任务管......
  • JVM堆外内存泄漏故障排查记录
    线上JVM堆外内存泄漏问题的排查过程与思路,其中夹带一些「JVM内存分配的原理分析」以及「常用的JVM问题排查手段和工具分享」,希望对大家有所帮助。在整个排查过程中,我也走了不少弯路,但是在文章中我仍然会把完整的思路和想法写出来,当做一次经验教训,给后人参考,文章最后也总结了下内......
  • Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump
    日志项目使用Maven的install打包,出现Pleaserefertodumpfiles(ifanyexist)[date].dump,[date]-jvmRun[N].dumpand[date].dumpstream.问题,导致打包失败。原因是Test类不通过,应该是测试代码有问题。解决方式一:选择下图的图标,然后install会跳过测试环节方式二:检......
  • JVM系统优化实践(13):GC动手实践
    您好,我是湘王,这是我的51CTO博客,欢迎您来,欢迎您再来~上一次留了个小尾巴:怎么以通过代码模拟对象年龄在15岁之后才进入老年代呢?自己试着实现了一下。首先需要设置好相关的JVM环境:-XX:InitialHeapSize=104857600-XX:MaxHeapSize=104857600-XX:NewSize=20971520-XX:MaxNewSize=209715......