Java问题排查工具箱
-
问题排查
- 解决思路,逻辑推导
- 工具
-
日志相关工具
- 日志的标准化
- to be continued...
- tail
- tail -f app-server.log
- tail -n 300 app-server.log
- find
- fgrep
- awk
- grep -C/A/B 30 'aaa' app-server.log
- 日志的标准化
-
CPU相关工具
-
top (real-time 观察系统的情况)
- top
- top -Hp <pid>
- top (press 1 show multi-cores, press 1 again to close, press q exit)
-
sar
- 查看历史指标数据,除了CPU外,其他内存,磁盘,网络等等各种指标都可以查看
-
jstack
- 通常对于应用没反应,非常慢等等场景
- jstack默认只能看到Java栈,而jstack -m则可以看到线程的Java栈和native栈,但如果Java方法被编译过,则看不到(然而大部分经常访问的Java方法其实都被编译过)
- -F 走JDK SA
- /proc/<pid>/mappings
- ptrace(PTRACE_ATTACH, PTRACE_PEEKDATA)
- 默认或-l走JDK Attach mechanism
- -m or -F走JDK SA mechanism
- java的tda工具就是专门分析thread dump的
- 在线分析工具
- kill -3 $PID / kill -QUIT $PID tomcat会把thread dump的内容输出到控制台
- We can use kill -3 PID command to generate the thread dump. This is slightly different from other ways to generate thread dump. When kill command is issued, thread dump is generated to the System out of the program. So if it’s a java program with console as system out, the thread dump will get printed on the console. If the java program is a Tomcat server with system out as catalina.out, then thread dump will be generated in the file.
死锁,Deadlock(重点关注)
执行中,Runnable
等待资源,Waiting on condition(重点关注)
等待获取监视器,Waiting on monitor entry(重点关注)
暂停,Suspended
对象等待中,Object.wait() 或 TIMED_WAITING
阻塞,Blocked(重点关注)
停止,Parked
-
jcmd
- Java 8 has introduced jcmd utility. You should use this instead of jstack if you are on Java 8 or higher. Command to generate thread dump using jcmd is jcmd PID Thread.print.
-
pstack
- pstack可以用来看Java进程的native栈
-
perf
- 一些简单的CPU消耗的问题靠着top -H + jstack通常能解决,复杂的话就需要借助perf这种超级利器了
-
cat /proc/interrupts
- 之所以提这个是因为对于分布式应用而言,频繁的网络访问造成的网络中断处理消耗也是一个关键,而这个时候网卡的多队列以及均衡就非常重要了,所以如果观察到cpu的si指标不低,那么看看interrupts就有必要了
-
-
内存相关工具
- jstat
- jstat -gcutil或-gc等等有助于实时看gc的状况,不过我还是比较习惯看gc log
- *.gc日志查看 or http://gceasy.io这个网站支持gc日志分析, *.gz or *.zip
- jmap
- memory dump分析内存泄漏
- 在需要dump内存看看内存里都是什么的时候,jmap -dump可以帮助你;在需要强制执行fgc的时候(在CMS GC这种一定会产生碎片化的GC中,总是会找到这样的理由的),jmap -histo:live可以帮助你(显然,不要随便执行)。
- gcore
- 相比jmap -dump,其实我更喜欢gcore,因为感觉就是更快,不过由于某些jdk版本貌似和gcore配合的不是那么好,所以那种时候还是要用jmap -dump的
- eclipse mat
- 有了内存dump后,没有分析工具的话然并卵,mat是个非常赞的工具,好用的没什么可说的?
- 我倾向于用IBM Memory Analyzer
- btrace
- 少数的问题可以mat后直接看出,而多数会需要再用btrace去动态跟踪,btrace绝对是Java中的超级神器,举个简单例子,如果要你去查下一个运行的Java应用,哪里在创建一个数组大小>1000的ArrayList,你要怎么办呢,在有btrace的情况下,那就是秒秒钟搞定的事
- gperf
- Java堆内的内存消耗用上面的一些工具基本能搞定,但堆外就悲催了,目前看起来还是只有gperf还算是比较好用的一个,或者从经验上来说Direct ByteBuffer、Deflater/Inflater这些是常见问题
- jstat
除了上面的工具外,同样内存信息的记录也非常重要,就如日志一样,所以像GC日志是一定要打开的,确保在出问题后可以翻查GC日志来对照是否GC有问题,所以像-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc: 这样的参数必须是启动参数的标配
-
ClassLoader相关工具
- 作为Java程序员,不碰到ClassLoader问题那基本是不可能的,在排查此类问题时,最好办的还是-XX:+TraceClassLoading,或者如果知道是什么类的话,我的建议就是把所有会装载的lib目录里的jar用jar -tvf *.jar这样的方式来直接查看冲突的class,再不行的话就要呼唤btrace神器去跟踪Classloader.defineClass之类的了
-
其他工具
- jinfo
- Java有N多的启动参数,N多的默认值,而任何文档都不一定准确,只有用jinfo -flags看到的才靠谱,甚至你还可以看看jinfo -flag,你会发现更好玩的
- dmesg
- 你的java进程突然不见了? 也许可以试试dmesg先看看
- systemtap
- 有些问题排查到java层面是不够的,当需要trace更底层的os层面的函数调用的时候,systemtap神器就可以派上用场了
- gdb
- 更高级的玩家们,拿着core dump可以用gdb来排查更诡异的一些问题
- jinfo
暂时就写这些,尽管工具的使用多数都可以临时学,但首先知道有哪些工具是最重要的,然后呢还是建议大家可以玩一玩这些工具,这样以后真的要用的时候也不至于一点印象都没有
-
References