java死锁性能分析

java故障诊断案例分析: 死锁瓶颈(性能分析)

只要是java程序, 都可以使用这种方式来分析性能的瓶颈

1. Dump信息查看

Thread dump信息对于性能诊断非常有用

  • kill 命令使用

    kill : 杀死一个进程

    ? -9: 强制杀死一个进程

    ? -3: 打印进程的Thread dump信息

  • linux系统: kill -3 pid
  • windows: 在命令行窗口上, 按一个组合键: ctrl + break(fn+B键)

2. 死锁程序分析

java的一个死锁程序代码:

public class DeadLock {

    final Object lockA = new Object();
    final Object lockB = new Object();

    public static void main(String[] args) {
        DeadLock demo = new DeadLock();
        demo.startLock();
    }

    private void startLock() {
        ThreadA a = new ThreadA(lockA, lockB);
        ThreadB b = new ThreadB(lockA, lockB);

        a.start();
        b.start();

    }
}

class ThreadA extends Thread {

    private Object lockA = null;
    private Object lockB = null;

    public ThreadA(Object a, Object b) {
        this.lockA = a;
        this.lockB = b;
    }

    public void run() {
        synchronized (lockA) {
            System.out.println("*** Thread A: ***: Lock A");
            try {
                sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lockB) {
                System.out.println("*** Thread B: ***: Lock B");

            }
        }
        System.out.println("*** Thread A: ***: Finished");

    }
}

class ThreadB extends Thread {

    private Object lockA = null;
    private Object lockB = null;

    public ThreadB(Object a, Object b) {
        this.lockA = a;
        this.lockB = b;
    }

    public void run() {
        synchronized (lockB) {
            System.out.println("*** Thread B: ***: Lock B");
            try {
                sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lockA) {
                System.out.println("*** Thread A: ***: Lock A");

            }
        }
        System.out.println("*** Thread B: ***: Finished");

    }
}
  1. 执行程序, 结果如下:
*** Thread A: ***: Lock A
*** Thread B: ***: Lock B
  1. 执行如下shell命令:
192:javatest lingjing$ jps
32246 Launcher
32247 DeadLock
32055
32248 Jps
192:javatest lingjing$ kill -3 32247
  1. 在原来程序的终端变成如下结果:
*** Thread A: ***: Lock A
*** Thread B: ***: Lock B
2019-05-26 11:01:24
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.151-b12 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=31 tid=0x00007fe4fa012000 nid=0x2603 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #12 prio=5 os_prio=31 tid=0x00007fe4fc82a000 nid=0xa603 waiting for monitor entry [0x00007000050a8000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at javatest.ThreadB.run(DeadLock.java:78)
    - waiting to lock <0x000000076ac6ca00> (a java.lang.Object)
    - locked <0x000000076ac6ca10> (a java.lang.Object)

"Thread-0" #11 prio=5 os_prio=31 tid=0x00007fe4fc801000 nid=0xa803 waiting for monitor entry [0x0000700004fa5000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at javatest.ThreadA.run(DeadLock.java:50)
    - waiting to lock <0x000000076ac6ca10> (a java.lang.Object)
    - locked <0x000000076ac6ca00> (a java.lang.Object)

"Service Thread" #10 daemon prio=9 os_prio=31 tid=0x00007fe4fd0d0000 nid=0x4103 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #9 daemon prio=9 os_prio=31 tid=0x00007fe4fd0d3000 nid=0x4303 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #8 daemon prio=9 os_prio=31 tid=0x00007fe4fd0d2000 nid=0x3f03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=31 tid=0x00007fe4fd0d1800 nid=0x3e03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=31 tid=0x00007fe4fd0d0800 nid=0x4703 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=31 tid=0x00007fe4fd0ce000 nid=0x4903 runnable [0x0000700004890000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    - locked <0x000000076adcaf90> (a java.io.InputStreamReader)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    - locked <0x000000076adcaf90> (a java.io.InputStreamReader)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fe4fa003800 nid=0x3d03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fe4f985b800 nid=0x3603 in Object.wait() [0x000070000468a000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076ab08ec8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
    - locked <0x000000076ab08ec8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007fe4fc815800 nid=0x3403 in Object.wait() [0x0000700004587000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x000000076ab06b68> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:502)
    at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
    - locked <0x000000076ab06b68> (a java.lang.ref.Reference$Lock)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=31 tid=0x00007fe4f985b000 nid=0x3203 runnable 

"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fe4f9800800 nid=0x1f07 runnable 

"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007fe4fc80a800 nid=0x2a03 runnable 

"GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007fe4fc001000 nid=0x2c03 runnable 

"GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007fe4fc80b000 nid=0x5303 runnable 

"GC task thread#4 (ParallelGC)" os_prio=31 tid=0x00007fe4fc80b800 nid=0x5203 runnable 

"GC task thread#5 (ParallelGC)" os_prio=31 tid=0x00007fe4fc80c000 nid=0x5003 runnable 

"GC task thread#6 (ParallelGC)" os_prio=31 tid=0x00007fe4fc80d000 nid=0x4f03 runnable 

"GC task thread#7 (ParallelGC)" os_prio=31 tid=0x00007fe4f9813000 nid=0x3003 runnable 

"VM Periodic Task Thread" os_prio=31 tid=0x00007fe4fd0d3800 nid=0x5503 waiting on condition 

JNI global references: 22

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x00007fe4fd005568 (object 0x000000076ac6ca00, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x00007fe4fd007d48 (object 0x000000076ac6ca10, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
    at javatest.ThreadB.run(DeadLock.java:78)
    - waiting to lock <0x000000076ac6ca00> (a java.lang.Object)
    - locked <0x000000076ac6ca10> (a java.lang.Object)
"Thread-0":
    at javatest.ThreadA.run(DeadLock.java:50)
    - waiting to lock <0x000000076ac6ca10> (a java.lang.Object)
    - locked <0x000000076ac6ca00> (a java.lang.Object)

Found 1 deadlock.

Heap
 PSYoungGen      total 76288K, used 10486K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000)
  eden space 65536K, 16% used [0x000000076ab00000,0x000000076b53d968,0x000000076eb00000)
  from space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)
  to   space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)
 ParOldGen       total 175104K, used 0K [0x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000)
  object space 175104K, 0% used [0x00000006c0000000,0x00000006c0000000,0x00000006cab00000)
 Metaspace       used 3297K, capacity 4500K, committed 4864K, reserved 1056768K
  class space    used 364K, capacity 388K, committed 512K, reserved 1048576K

在上面的程序中, 如下的一段, 我们可以发现一个死锁, 并给出一个提示, 并提示我们在代码的78行和50行有错误, 所以我们分析代码逻辑, 来帮助我们找到死锁的节点

Java stack information for the threads listed above:
===================================================
"Thread-1":
    at javatest.ThreadB.run(DeadLock.java:78)
    - waiting to lock <0x000000076ac6ca00> (a java.lang.Object)
    - locked <0x000000076ac6ca10> (a java.lang.Object)
"Thread-0":
    at javatest.ThreadA.run(DeadLock.java:50)
    - waiting to lock <0x000000076ac6ca10> (a java.lang.Object)
    - locked <0x000000076ac6ca00> (a java.lang.Object)

Found 1 deadlock.

3. java性能分析工具thread dump和heap dump

1. dump基本概念

在故障定位(尤其是out of memory)和性能分析的时候,经常会用到一些文件来帮助我们排除代码问题。这些文件记录了JVM运行期间的内存占用、线程执行等情况,这就是我们常说的dump文件。常用的有heap dump和thread dump(也叫javacore,或java dump)。我们可以这么理解:heap dump记录内存信息的,thread dump是记录CPU信息的。

heap dump:

? heap dump文件是一个二进制文件,它保存了某一时刻JVM堆中对象使用情况。HeapDump文件是指定时刻的Java堆栈的快照,是一种镜像文件。Heap Analyzer工具通过分析HeapDump文件,哪些对象占用了太多的堆栈空间,来发现导致内存泄露或者可能引起内存泄露的对象。

thread dump:

? thread dump文件主要保存的是java应用中各线程在某一时刻的运行的位置,即执行到哪一个类的哪一个方法哪一个行上。thread dump是一个文本文件,打开后可以看到每一个线程的执行栈,以stacktrace的方式显示。通过对thread dump的分析可以得到应用是否“卡”在某一点上,即在某一点运行的时间太长,如数据库查询,长期得不到响应,最终导致系统崩溃。单个的thread dump文件一般来说是没有什么用处的,因为它只是记录了某一个绝对时间点的情况。比较有用的是,线程在一个时间段内的执行情况。

两个thread dump文件在分析时特别有效,困为它可以看出在先后两个时间点上,线程执行的位置,如果发现先后两组数据中同一线程都执行在同一位置,则说明此处可能有问题,因为程序运行是极快的,如果两次均在某一点上,说明这一点的耗时是很大的。通过对这两个文件进行分析,查出原因,进而解决问题。

2. 利用JDK自动的工具获取thread dump文件和heap dump

使用的JDK工具在JDK_HOME/bin/目录下,使用到jmap和jstack这两个命令。

1.获取heap dump文件

jmap -dump:format=b,file=heap.out 32274
#执行结果如下:
Dumping heap to /Users/lingjing/IdeaProjects/javatest/heap.out ...
Heap dump file created

这样就会在当前目录下生成heap.out文件,这就是heap dump文件。

  1. 获取thread dump文件
jstack 32274 >thread.out

结果转储到thread.out,这就是thread dump文件。有了dump文件后,我们就能借助性能分析工具获取dump文件中的信息。

  1. java heap dump工具分析

因为我们抓取的heap信息是二进制文件, 如果我们需要分析heap信息, 就需要借助一下分析工具, jhat是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。

jhat  -port 5001 heap.out

当服务启动完成以后, 我们可以在浏览器中通过http://127.0.0.1:5001/进行访问

原文地址:https://www.cnblogs.com/lingshang/p/10925894.html

时间: 2024-11-07 16:27:51

java死锁性能分析的相关文章

Java application 性能分析分享

性能分析的主要方式 监视:监视是一种用来查看应用程序运行时行为的一般方法.通常会有多个视图(View)分别实时地显示 CPU 使用情况.内存使用情况.线程状态以及其他一些有用的信息,以便用户能很快地发现问题的关键所在. 转储:性能分析工具从内存中获得当前状态数据并存储到文件用于静态的性能分析.Java 程序是通过在启动 Java 程序时添加适当的条件参数来触发转储操作的.它包括以下三种: 系统转储:JVM 生成的本地系统的转储,又称作核心转储.一般的,系统转储数据量大,需要平台相关的工具去分析,

Android开发之Java集合类性能分析

对于Android开发者来说深入了解Java的集合类很有必要主要是从Collection和Map接口衍生出来的,目前主要提供了List.Set和 Map这三大类的集合,今天就他们的子类在标准情况和多线程下的性能做简单的分析. Collection接口主要有两种子类分别为List和Set,区别主要是List保存的对象可以重复,而Set不可以重复,而Map一般为key-value这样的对应关系,比如我们常用的HashMap. 一.List 主要有ArrayList.LinkedList.Vector

java进程性能分析步骤-超越昨天的自己系列(11)

java进程load过高分析步骤: top 查看java进程情况 top -Hp 32323 查看某个进程的具体线程情况 printf 0x%x 31973 确认哪一个线程占用cpu比较多,拿出来转成16进制 jstack 32323> jstack.log 注:jstack命令必须由当前运行的java进程用户执行,否则会出现“12377: Operation not permitted”错误 最后: 在jstack.log  中查询相关线程的信息

java&amp;nbsp;IO性能分析(转载)

Java IO性能分析 第一部分技术讨论底层的I/O问题,然后讨论诸如压缩,格式化和串行化等高级I/O问题.然而这个讨论没有包含应用设计问题,例如搜索算法和数据结构,也没有讨论系统级的问题,例如文件高速缓冲. Java语言采取两种截然不同的磁盘文件结构.一个是基于字节流,另一个是字符序列.在Java语言中一个字符有两个字节表示,而不是像通常的语言如c语言那样是一个字节.因此,从一个文件读取字符时需要进行转换.这个不同在某些情况下是很重要的,就像下面的几个例子将要展示的那样. 低级I/O相关的问题

性能分析之-- JAVA Thread Dump 分析综述

性能分析之-- JAVA Thread Dump 分析综述 一.Thread Dump介绍 1.1什么是Thread Dump? Thread Dump是非常有用的诊断Java应用问题的工具.每一个Java虚拟机都有及时生成所有线程在某一点状态的thread-dump的能力,虽然各个 Java虚拟机打印的thread dump略有不同,但是大多都提供了当前活动线程的快照,及JVM中所有Java线程的堆栈跟踪信息,堆栈信息一般包含完整的类名及所执行的方法,如果可能的话还有源代码的行数. 1.2 T

Java 性能分析工具

如何利用 JConsole观察分析Java程序的运行,进行排错调优 http://jiajun.iteye.com/blog/810150 如何使用JVisualVM进行性能分析 http://jiajun.iteye.com/blog/1180230 全功能的Java剖析工具(profiler) http://www.blogjava.net/mrzhangshunli/archive/2007/08/27/140088.html http://www.cnblogs.com/jayzee/p

Java性能优化指南系列(二):Java 性能分析工具

进行JAVA程序性能分析的时候,我们一般都会使用各种不同的工具.它们大部分都是可视化的,使得我们可以直观地看到应用程序的内部和运行环境到底执行了什么操作,所以性能分析(性能调优)是依赖于工具的.在第2章,我强调了基于数据驱动的性能测试是非常重要的,我们必须测试应用的性能并理解每个指标的含义.性能分析和数据驱动非常类似,为了提升应用程序的性能,我们必须获取应用运行的相关数据.如何获取这些数据并理解它们是本章的主题.[本章重点介绍JDK中提供的性能分析工具] 操作系统工具及其分析 程序分析的起点并不

SQL SERVER性能分析--死锁检测数据库阻塞语句

工作中数据库经常出现内存,找了篇文章 参照CSDN,中国风(Roy)一篇死锁文章 阻塞:其中一个事务阻塞,其它事务等待对方释放它们的锁,同时会导致死锁问题. 整理人:中国风(Roy) 参照Roy_88的博客 http://blog.csdn.net/roy_88/archive/2008/07/21/2682044.aspx 日期:2008.07.20 ************************************************************************

Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和性能分析)

java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 Java 集合系列 05 Vector详细介绍(源码解析)和使用示例 Java 集合系列 06 Stack详细介绍(源码解析)和使用示例 Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和