作为一个高级Java开发人员,经常会碰到一些jvm的异常问题。譬如一些JVM引起的进程内存耗用过高,CPU负载高,等等。那么遇到这些问题应该怎么解决呢?接下来我们将就此问题展开:
首先,我们需要找出资源耗用异常的进程,我们以Linux为例,执行top命令:
1.top
假设我们获取到第一个进程的资源耗用异常,紧接着我们需要找到进程内资源耗用异常的线程,我们可以执行命令:
2.top -H PID
拿到异常线程id之后,我们需要找到JVM线程栈里的信息,因为在线程栈中,线程id是以十六进制存在的,所以,我们需要把它转成十六进制:
3.printf "%x\n" TID
之后,我们就可以通过线程栈信息获得线程内执行的内容:
4.jstack PID|grep TID
我们也可把全部的线程栈打印出来,通过ha工具分析
jstack PID > <filename>
接下来就很简单了,我们只要分析一下线程栈里的代码就能定位到问题了。十有八九是我们自己写的代码有bug。
这里还有一套组合拳,可以定位出进程内线程资源耗用排行
ps -mp PID -o THREAD,tid,time | sort -rn
有时候通过线程栈不能很好的显示出问题,我们也可从侧面看看JVM的配置是否合理:
jinfo -flags PID
我们还可以通过jstat看看GC的情况,
jstat -gcutil pid
有时候jstat并不能很好的显示gc信息,我们需要打印gc日志,需要添加jvm启动参数:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:<file-path>
还有一些方法,譬如说,我们想查看某一线程的系统调用,从系统调用中找出一些端倪:
strace -p tid
我们还可以通过jmap命令打出线程的内存信息:
jmap -dump:format=b,file=<filename> PID
根据经验来看,一般来说资源耗用异常十有八九是我们自己的代码问题。
最后,介绍两个耗用的工具,一个是堆栈查看工具,一个是内存查看工具:ha和jca
ha456.jar下载