BYTECODES

Java生产环境下问题排查

在生产环境中,我们无法通过断点调试、新增log、可视化工具去立马查看当前的运行状态和拿到错误信息,此时,借助Java自带的命令行工具以及相关dump分析工具以及一些小技巧,可以大大提升我们排查问题的效率。

一、运行参数

查看JVM参数

jps -ml 查看所有正在运行的Java程序,同时显示启动类类名,获取到PID

jinfo -flags PID 查看运行时进程参数与JVM参数

查看当前虚拟机默认JVM参数

java -XX:+PrintFlagsFinal -version

查看即时GC状态

jstat -gc PID 1000 10 每秒查看一次gc信息,共10次

输出比较多的参数,每个字段的解释参看 https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html

二、错误排查

内存问题

  1. 导出Dump文件

    . 提前对Java程序加上这些参数印dump文件 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./

    . 对正在运行的程序使用jmap:jmap -dump:format=b,file=heap.hprof PID

  2. 分析Dump文件

    如果Dump文件不太大的话,可以传到 http://heaphero.io/index.jsp 来分析

    如果文件太大,或者想更细致分析,可以使用[MAT][1], 有如下几种常用查看方式:

    . 首页中的【Leak Suspects】能推测出问题所在

    . 点击【Create a histogram from an arbitrary set of objects】查到所有对象的数量

    . 右键点击某个对象【Merge Shortest Paths to GC Roots】-> 【exclude all phantom/weak/soft etc. references】能查询到大量数量的某个对象是哪个GC ROOT引用的

线程问题

任务长时间不退出?CPU 负载过高?很可能因为死循环或者死锁,导致某些线程一直执行不被中断,但是不报错是最烦人的,所以日志里看不到错误信息,并且又不能用dump文件分析,因为跟内存无关。这个时候就需要用线程分析工具来帮我们了。

  1. 导出jstack文件

    使用jstack PID > 文件,如果失败请加-F参数,如果还失败请使用Java程序启动时使用的用户执行jstack,下面是jstack的部分输出格式。

jstack的输出可以看到所有的线程以及他们的状态,我们就可以看有哪些我们自己创建的正在运行的线程,那很可能就是那个一直在执行的线程了,此时线程名就格外重要了,所以建议创建新线程时指定有意义的线程名。当然,通过PID查找也非常方便。

  1. 排查步骤

    . top 查看到哪个java程序负载高

    . top -p PID -H 查看该进程所有进程的运行状态

    . 记录下高负载的线程ID,printf "&x" PID转换成16进制

    . jstack PID > 文件

    . 在jstack文件中用转换成16进制之后的线程ID查询线程运行堆栈

    . 从堆栈中了解到线程在执行什么任务,并结合业务与代码判断问题所在

附录

文章来源: https://www.wangtianyi.top/blog/2018/07/20/javasheng-chan-huan-jing-xia-wen-ti-pai-cha


[1]: https://www.eclipse.org/mat/