(摘自网络)

一、CPU过高

这是最常发生的让人很纠结的问题,CPU 100%了 ,但到底是什么引发的呢? 使用Jprofiler之类的工具可以查看CPU问题,能列出CPU具体堆栈,但是有个问题是Jprofiler本身会占用很高的CPU,用Jprofiler来查看CPU问题的时候会很不靠谱。 下面介绍一些比较简单的查看CPU高的方法。

首先来看哪些线程占用了最多的CPU

  • ps -eLo pid,lwp,pcpu | grep |sort -nk 3
    该方法可以找到CPU占用前3的线程
  • top -H
    该方法能列出占用最高的那些线程
    通过上述方法可以知道有问题的线程的pid,然后将该线程号由10进制改为16进制。

接下来来看线程的堆栈

jstack -l 该方法打出进程的所有线程堆栈,查找16进制的线程号,nid=0x17a1 这个就是线程号的位置 比如

"FelixStartLevel-SendThread(db-3.photo.163.org:2181)" daemon prio=10 tid=0x00007fba6406a800 nid=0x17a1 runnable [bidw:0x000000004027c000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:228)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:83)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
        - locked <0x00007fba7d9c2d80> (a sun.nio.ch.Util$1)
        - locked <0x00007fba7d9c31c0> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00007fba7d9c2dd8> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
        at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1107)
   Locked ownable synchronizers:
        - None

这个jstack只是一个采样的方法,看当前线程执行的位置。 但我们可以假设在CPU100%的情况下,你基本上采样都是在出问题的语句上。因此这个堆栈的第一行 at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) 就是CPU出问题的地方。可以多用jstack采样几次 ,看看是否都在同一个地方。 这个方法很简单,屡试不爽,也不需要安装软件,方便使用。

二、内存OOM

内存OOM是大家常见的问题,线上遇到OOM不要慌,别先记着重启,第一步先把内存堆栈打印出来 jmap -dump:live,format=b,file= 如果线上经常经常出现OOM问题也可以在JVM参数里加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath= 在进程OOM时自动dump出内存堆栈 有了内存堆栈就好办了,给大家介绍个工具MAT,是我觉得最好用的内存分析工具http://www.eclipse.org/mat/

pic

leak suspects帮助你分析内存泄露可能的地方,像我上面的例子就看出ShutDownHook有问题,溢出了
但是溢出的对象从哪里来,可以在details中点击list objects-> Incoming references

pic

就能够看到引用对象的引用来源,这样就一目了然了哪里有泄露 三、句柄泄露 这是大部分java开发者不太会关心的一个问题,写过C程序的开发者会比较容易重视这个问题。正因为不重视所以还是很容易出现的。 大部分的监控平台都有CPU、内存、硬盘的监控,但很多没有句柄的监控。最后程序发生too many open files了,却不知道。 句柄泄露的查看方式很简单,可以用lsof -p ,查看进程所占用的所有句柄,当句柄泄露的时候肯定会有部分句柄出现极为异常的数量。 lsof -p 6022 java 6022 fs 1w REG 8,8 5006 3014678 /home/xxx/log.log java 6022 fs 2w REG 8,8 5006 3014678 /home/xxx/log.log 需要仔细检查句柄占用过多的文件代码是否有问题。