使用 thread dump
将会介绍三种常用的方法。请注意还会有其他很多方法可以获取Thread Dump。一个Thread dump仅仅可以显示测量时的线程状态。所以为了查看线程状态的变化,建议5到10次,每次间隔5秒。
kill -3 生成的dump文件默认不是独立的文件,而jstack命令则是生成的独立文件。
Solaris OS 下,使用kill -QUIT。---这个待实验。
linux/unix
linux下执行Kill -3 PID可以生成jvm的thread dump
$ ps - ef | grep java 获得当前正在运行的java进程pid
kill -3
注意生成的dump信息位置,如果nohup启动则会在nohup日志中,如果是按sh start.sh这种形式,则默认在日志文件中(tomcat的为catalina.out)
必要性:比如openJDK无法使用jstack命令时,就可以使用kill -3的方式来dump。
使用Java命令jstack获得Thread dump
1)获取java进程pid,获取方式如jps -v命令,ps -ef|grep java命令,top命令等等。。
2)jstack -f
jstack命令有几项参数,根据实际需要获取。
dump的信息为独立的文件。
使用jvisualvm工具获得Thread dump****
Jvisualvm工具连接指定Java,使用工具生成。
[图片上传失败...(image-b140d3-1663587485587)]
左边的标记,当前正在运行的进程。点击想查看的进程,选择现场选项来查看实时的线程信息。点击Thread dump右边的按钮来获得Thread dump文件
windows
在Windows下可以在JVM的console窗口上敲Ctrl-Break。根据不同的设置,thread dump会输出到当前控制台上或应用服务器的日志里。
如果想将日志输出到文件,可以修改tomcat/bin目录下的“catalina.bat”,在文件最后的四个ACTION后增加“>>%CATALINA_BASE%/logs/thread_demp.out”,同时修改bin目录下的startup.bat为:
rem call "%EXECUTABLE%" start "%CMD_LINE_ARGS%"
call "%EXECUTABLE%" run "%CMD_LINE_ARGS%"
这样就可以将日志输出到logs下的thread_dump.out文件中。也可以下载相应的分析工具对其进行分析。需要说明的一点是,将startup.bat修改为以上内容后,关闭tomcat时,直接关闭DOS窗口就可以了,不用shutdown.bat。
分析Thread dump
逆向分析:线程堆栈里面的最直观的信息是当前线程的调用上下文,即从哪个函数调用到哪个函数(从下往上看),正执行到哪一类的哪一行。
at java.net.SocketInputStream.read(SocketInputStream.java:129)
SocketInputStream 类名
read 方法名
SocketInputStream.java 源文件
129 源文件中的行数
在堆栈的第一行信息中,进一步标明了线程在代码级的状态,例如:
java.lang.Thread.State: TIMED_WAITING (parking)
解释如下:
|blocked|
This thread tried to enter asynchronized block, but the lock was taken by another thread. This thread isblocked until the lock gets released.
|blocked (on thin lock)|
This is the same state asblocked, but the lock in question is a thin lock.
|waiting|
This thread calledObject.wait() on an object. The thread will remain there until some otherthread sends a notification to that object.
|sleeping|
This thread calledjava.lang.Thread.sleep().
|parked|
This thread calledjava.util.concurrent.locks.LockSupport.park().
|suspended|
The thread's execution wassuspended by java.lang.Thread.suspend() or a JVMTI agent call.
本地线程ID
"NativeThread ID"所指的本地线程是指该java虚拟机所对应的虚拟机中的本地线程,java代码是依附于java虚拟机的本地线程执行的,当启动一个线程时,是创建一个native本地线程,本地线程才是真实的线程实体,为了更加深入理解本地线程和java线程的关系,可以通过以下方式将java虚拟机的本地线程打印出来:
1、试用ps -ef|grep java 获得java进行id
2、试用pstack
从操作系统打印出来的虚拟机的本地线程看,本地线程数量和java线程数量是相同的,说明二者是一一对应的关系。
那么本地线程号如何与java线程堆栈文件对应起来呢,每一个线程都有tid,nid的属性。nid即为dump线程的nid。
原文参考地址