如何分析java Thread DUMP
发布网友
发布时间:2022-04-25 19:24
我来回答
共3个回答
热心网友
时间:2022-04-08 03:33
一、Thread Dump介绍
1.1什么是Thread Dump?
Thread Dump是非常有用的诊断Java应用问题的工具。每一个Java虚拟机都有及时生成所有线程在某一点状态的thread-mp的能力,虽然各个 Java虚拟机打印的thread mp略有不同,但是大多都提供了当前活动线程的快照,及JVM中所有Java线程的堆栈跟踪信息,堆栈信息一般包含完整的类名及所执行的方法,如果可能的话还有源代码的行数。
1.2 Thread Dump特点
1. 能在各种操作系统下使用
2. 能在各种Java应用服务器下使用
3. 可以在生产环境下使用而不影响系统的性能
4. 可以将问题直接定位到应用程序的代码行上
1.3 Thread Dump 能诊断的问题
1. 查找内存泄露,常见的是程序里load大量的数据到缓存;
2. 发现死锁线程;
1.4如何抓取Thread Dump
一般当服务器挂起,崩溃或者性能底下时,就需要抓取服务器的线程堆栈(Thread Dump)用于后续的分析. 在实际运行中,往往一次 mp的信息,还不足以确认问题。为了反映线程状态的动态变化,需要接连多次做threadmp,每次间隔10-20s,建议至少产生三次 mp信息,如果每次 mp都指向同一个问题,我们才确定问题的典型性。
有很多方式可用于获取ThreadDump, 下面列出一部分获取方式:
操作系统命令获取ThreadDump:
Windows:
1.转向服务器的标准输出窗口并按下Control + Break组合键, 之后需要将线程堆栈复制到文件中;
UNIX/ Linux:
首先查找到服务器的进程号(process id), 然后获取线程堆栈.
1. ps –ef | grep java
2. kill -3 <pid>
注意:一定要谨慎, 一步不慎就可能让服务器进程被杀死。kill -9 命令会杀死进程。
JVM 自带的工具获取线程堆栈:
JDK自带命令行工具获取PID,再获取ThreadDump:
1. jps 或 ps –ef|grepjava (获取PID)
2. jstack [-l ]<pid> | tee -a jstack.log (获取ThreadDump)
二、java线程的状态转换介绍(为后续分析做准备)
2.1 新建状态(New)
用new语句创建的线程处于新建状态,此时它和其他Java对象一样,仅仅在堆区中被分配了内存。
2.2 就绪状态(Runnable)
当一个线程对象创建后,其他线程调用它的start()方法,该线程就进入就绪状态,Java虚拟机会为它创建方法调用栈和程序计数器。处于这个状态的线程位于可运行池中,等待获得CPU的使用权。
2.3 运行状态(Running)
处于这个状态的线程占用CPU,执行程序代码。只有处于就绪状态的线程才有机会转到运行状态。
2.4 阻塞状态(Blocked)
阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,Java虚拟机不会给线程分配CPU。直到线程重新进入就绪状态,它才有机会转到运行状态。
阻塞状态可分为以下3种:
1)位于对象等待池中的阻塞状态(Blocked in object’s wait pool):当线程处于运行状态时,如果执行了某个对象的wait()方法,Java虚拟机就会把线程放到这个对象的等待池中,这涉及到“线程通信”的内容。
2)位于对象锁池中的阻塞状态(Blocked in object’s lock pool):当线程处于运行状态时,试图获得某个对象的同步锁时,如果该对象的同步锁已经被其他线程占用,Java虚拟机就会把这个线程放到这个对象的锁池中,这涉及到“线程同步”的内容。
热心网友
时间:2022-04-08 04:51
当Java Web程序运行变慢,或者发生故障时,需要使用Thread Dumps. 如果觉得ThreadDumps非常复杂,这篇文章很可能帮助你。将会分析Java中的线程,线程如何创建的,如何管理线程,怎么从运行中的程序中mp 线程,最后怎么分析他们得到阻塞和存在瓶颈的线程。
热心网友
时间:2022-04-08 06:26
当Java Web程序运行变慢,或者发生故障时,需要使用Thread Dumps. 如果你觉得ThreadDumps非常复杂,这篇文章很可能帮助你。将会分析Java中的线程,线程如何创建的,如何管理线程,怎么从运行中的程序中mp 线程,最后怎么分析他们得到阻塞和存在瓶颈的线程。本文是在应用程序调试下得到的结果。
Java和线程
一个web server使用几十到几百条线程去处理大量的并发用户。如果多条线程使用共享的资源,无法避免线程之间对数据的竞争,有时候还会发生死锁。
线程竞争是web程序上不同的线程去访问共享资源,一条线程等待另外线程释放锁。例如,在记录log的时候,线程记录log时,必须先获得锁,然后去再访问共享资源。
死锁是一种特殊的线程竞争,两个或多个线程要完成自己的任务,都要必须要等待其他的线程完成他们的任务。
线程竞争会带来各种不同的问题,为了分析这些问题,需要使用Thread Dump。Thread Dump记录了每个线*正的状态。
Java线程的背景
线程同步
多条线程之间可以同时执行,为了确保多线程在使用共享资源上面的通用性,使用线程同步保证在同一时间只能有一条线程可以访问共享资源。
线程同步在Java中可以使用监视器。每个Java对象都有一个监视器,这个监视器只能被一个线程拥有。当一个线程要获得另外线程拥有的监视器时,需要进入等待队列直到线程释放监视器。
线程的状态
为了分析Thread Dump ,需要先了解线程的状态。线程的状态是在java.lang.Thread.State中。
NEW:线程被创建但是还没有被执行
RUNNABLE:线程正在占用cpu并且在执行任务
BLOCKED:线程为了获得监视器需要等待其他线程释放锁
WAITING:调用了wait,join,park方法使线程等待-无限期等待
TIMED_WAITING:调用了sleep,wait,join,park方法使线程等待--有限期等待
线程类型
java中线程可以分为两种:
1. 后台线程
2. 非后台线程
当没有其他的非后台线程运行时后台线程将会终止。即使你不创建线程,java应用默认也会创建很多线程。这些大多数都是后台线程,主要为了执行gc或者jmx等类型的任务
从 'static void main(String[] args)’方法中开启的线程叫做非后台线程,当这些线程停止时,其他的所有后台线程也会停止()
获得一个Thread Dump
将会介绍三种常用的方法。请注意还会有其他很多方法可以获取Thread Dump。一个Thread mp仅仅可以显示测量时的线程状态。所以为了查看线程状态的变化,建议5到10次,每次间隔5秒。
使用jstack获得Thread Dump
通过使用jsp命令来获得当前正在运行的Java程序的PID
[user@linux ~]$ jps -v 25780 RemoteTestRunner -Dfile.encoding=UTF-8 25590 sub.rmi.registry.RegistryImpl 2999 -Dapplication.home=/home1/user/java/jdk.1.6.0_24 -Xms8m 26300 sun.tools.jps.Jps -mlvV -Dapplication.home=/home1/user/java/jdk.1.6.0_24 -Xms8m
使用PID作为jstack的参数获得Thread Dump
[user@linux ~]$ jstack -f 5824
使用jVisualVM获得Thread Dump
通过使用jVisualVm来获得Thread Dump
左边的标记,当前正在运行的进程。点击你想查看的进程,选择现场选项来查看实时的线程信息。点击Thread Dump右边的按钮来获得Thread Dump文件
在Linux终端中生成
通过使用ps -ef命令去获得当前正在运行的Java进程
[user@linux ~]$ ps - ef | grep java
user 2477 1 0 Dec23 ? 00:10:45 ...
user 25780 25361 0 15:02 pts/3 00:00:02 ./jstatd -J -Djava.security.policy=jstatd.all.policy -p 2999
user 26335 25361 0 15:49 pts/3 00:00:00 grep java
Use the extracted pid as the parameter of kill –SIGQUIT(3) to obtain a thread mp.
Thread Information from the Thread Dump File
"pool-1-thread-13" prio=6 tid=0x000000000729a000 nid=0x2fb4 runnable [0x0000000007f0f000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:129) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) - locked <0x0000000780b7e688> (a java.io.InputStreamReader) at java.io.InputStreamReader.read(InputStreamReader.java:167) at java.io.BufferedReader.fill(BufferedReader.java:136) at java.io.BufferedReader.readLine(BufferedReader.java:299) - locked <0x0000000780b7e688> (a java.io.InputStreamReader) at java.io.BufferedReader.readLine(BufferedReader.java:362)
Thread name:当使用 Java.lang.Thread类去生成一个线程,将被命名为Thre-(Number),然而当使用java.util.concurrent,ThreadFactory类,将会被命名为pool-(Number)-thread-(Number)
Priority:表示线程的优先级
Thread ID:代表线程的唯一id。(通过线程id可以获得一些有用的信息,包括cpu使用率,或者内存使用率)
Thread status:代表线程的状态
Thread callstack:代表线程调用的堆栈信息
Thread Dump模式的类型
当无法获得一个锁(阻塞)
当一个线程占领住锁而其他线程无法获得这个锁,而导致应用程序所有的性能都下降。