线程快照即Thread Dump,通过
Thread Dump可以观察线程的状态以及堆栈跟踪信息。
获取Thread Dump
- 通过jstack命令(推荐在远程Linux环境机器上使用)
在jdk的bin目录下可以找到这个命令,
jps 或 ps –ef|grep java (获取PID)
jstack [-l ]<pid> | tee -a jstack.log (获取ThreadDump)
- 通过jVisualVM (推荐在本地win环境下使用)
在jdk安装目录下bin目录下双击jvisualvm.exe即可。可以监视本地Java程序,也可以通过配置服务器的JMX或jstatd来监视远程Java程序。
1、在weblogic中启用JMX的方法为:
找到相应的Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh文件,在文件最后添加
JAVA_OPTIONS="${JAVA_OPTIONS} -Djava.rmi.server.hostname=192.168.1.110"
JAVA_OPTIONS="${JAVA_OPTIONS} -Djavax.management.builder.initial=weblogic.management.jmx.mbeanserver.WLSMBeanServerBuilder"
JAVA_OPTIONS="${JAVA_OPTIONS} -Dcom.sun.management.jmxremote=true"
JAVA_OPTIONS="${JAVA_OPTIONS} -Dcom.sun.management.jmxremote.port=51234"
JAVA_OPTIONS="${JAVA_OPTIONS} -Dcom.sun.management.jmxremote.ssl=false"
JAVA_OPTIONS="${JAVA_OPTIONS} -Dcom.sun.management.jmxremote.authenticate=false"
来修改Java启动参数,其中192.168.1.110为远程机器的ip地址(通过ifconfig命令查看),51234为自定义的端口(要求在允许的范围内不冲突)。然后在本地的jVisualVM上添加远程主机,再添加JMX连接即可。
2、在服务器启用jstatd的方法为:
首先要确定服务器上安装了jdk,通过Java -version来查看。可以在jdk安装目录下的bin目录下找到jstatd命令。先新建一个 jstatd.all.policy文件,内容如下:
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
然后通过 ./jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.logCalls=true命令启用jstatd。此时jVisualVM就能监视到远程Java程序。
获取ThreadDump的方式如图,线程Dump就是。但是此种方式的dump文件内容没有通过jstack命令获取的丰富。而且通过jstatd方式远程连接无法获取。
分析Thread Dump
以下为我提取的threadDump的部分内容。
[tianyuan@landingbj bin]$ more threadDump
1975-09-05 04:03:58
Full thread dump Java HotSpot(TM) Client VM (20.4-b02 mixed mode):
"RMI TCP Connection(19)-192.168.1.104" daemon prio=10 tid=0x0871a400 nid=0x5238 runna
ble [0x814fe000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
- locked <0x8a240270> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:66)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:517)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.jav
a:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java
:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.
java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java
:908)
at java.lang.Thread.run(Thread.java:662)
Locked ownable synchronizers:
- <0x8a27ab68> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
解释如下,
* 线程名称:RMI TCP Connection(19)-192.168.1.104
* 线程类型:daemon
* 优先级: 10,默认是5
* jvm线程id:tid=0x0871a400,jvm内部线程的唯一标识(通过java.lang.Thread.getId()获取,通常用自增方式实现。)
* 对应系统线程id(NativeThread ID):nid=0x5238 ,和top命令查看的线程pid对应,不过一个是10进制,一个是16进制。(通过命令:top -H -p pid,可以查看该进程的所有线程信息)
* 线程状态: runnable
* 起始栈地址:[0x814fe000]
* Java thread statck trace:余下部分的信息。到目前为止这是最重要的数据,Java stack trace提供了大部分信息来精确定位问题根源。
参考:
http://blog.csdn.net/rachel_luo/article/details/8920596
http://segmentfault.com/blog/yexiaobai/1190000000615690