美文网首页
05_内存溢出_分析

05_内存溢出_分析

作者: 王康健_0124 | 来源:发表于2019-03-25 00:10 被阅读0次

    什么是堆Dump

    堆Dump是反应Java堆使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。 一般,在内存不足、GC异常等情况下,我们就会怀疑有内存泄露。这个时候我们就可以制作堆Dump来查看具体情况。
    当我们在做压测的时候,如果遇到服务器返回

    outOfMemoryError 年老代内存不足。
    outOfMemoryError:PermGen Space 永久代内存不足。
    outOfMemoryError:GC overhead limit exceed 垃圾回收时间占用系统运行时间的98%或以上
    

    这说明你的jvm中堆的内存不足,GC无法进行回收
    这个时候我们就需要去分析因为是因为说明原因造成的!

    注:当有内存溢出,程序无法访问的时候,不要赶紧去重启服务器,首先我们可以把堆中的信息dump下来

    这里介绍一下jmap这个命令:

    jmap -dump:将内存使用的详细情况输出到文件

    • 这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用。

    linux中输入jmap查看帮助文档,关于jmap -dump给了详细的example,我们只需要拷贝一下,然后把pid改成tomcat启动的进程号就行

    例:
    先查看启动的tomcat进程号:ps -ef|grep tomcat


    执行:jmap -dump:live,format=b,file=heap.bin 1163

    会在当前的目录下面生成一个heap.bin文件,这样就把堆中的信息dump下来,然后可以利用eclipse的mat插件进行分析
    mat下载地址
    提取码:6j78

    然后file--open file 找的从linux中下载到本地的heap.bin文件(具体的使用方法就不教了,网上可自行看一下)

    也可以使用 jhat 打开刚刚dump下来的文件,主要是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。:

    执行:jhat heap.bin
    启动一个http服务,端口要是7000,在浏览器中输入本机的ip,加上端口号7000
    Started HTTP server on port 7000
    

    jhat详细介绍:https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html

    通过命令查看大对象

    jmap -histo <pid>|less
    进入命令要退出: q

    • 可得到如下包含对象序号、某个对象示例数、当前对象所占内存的大小、当前对象的全限定名,

    如下图:

    查看对象数最多的对象,并按降序排序输出:
    执行:jmap -histo <pid>|grep tomcat|sort -k 2 -g -r|less

    查看占用内存最多的最象,并按降序排序输出:
    执行:jmap -histo <pid>|grep tomcat|sort -k 3 -g -r|less

    结果如图

    友情提示:jmap -histo:live pid>a.log,可以先将命令结果重定向到一个文件中,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象!
    #instance 是对象的实例个数 
    #bytes 是总占用的字节数 
    class name 对应的就是 Class 文件里的 class 的标识 
    B 代表 byte
    C 代表 char
    D 代表 double
    F 代表 float
    I 代表 int
    J 代表 long
    Z 代表 boolean
    前边有 [ 代表数组, [I 就相当于 int[]
    对象用 [L+ 类名表示
    

    jstat -gcutil 实时查看堆运行情况
    命令:jstat -gcutil 1163 2000 10
    jstat -gcutil pid 多久展现一次 展现多少次

    S0:第一个幸存区的使用大小
    S1:第二个幸存区的使用大小
    E:伊甸园区的使用大小
    O:老年代使用大小
    M:方法区使用大小
    CCS:压缩类空间使用大小
    YGC:年轻代垃圾回收次数
    YGCT:年轻代垃圾回收消耗时间
    FGC:老年代垃圾回收次数
    FGCT:老年代垃圾回收消耗时间
    GCT:垃圾回收消耗总时间
    

    当FGC一直在增加,O达到了95%或者100%的时候,由于内存不住,会执行fullGC回收内存,但是由于老年区的内存被占用无法进行回收,两者冲突就会不断的执行FGC,增加FQC的次数!这个时候你就需要去排查

    性能问题查找

    1、发现问题
    1)、使用uptime命令查看CPU的Load情况,Load越高说明问题越严重;
    2)、使用jstat查看FGC发生的频率及FGC所花费的时间,FGC发生的频率越快、花费的时间越高,问题越严重;

    总结
    1.如果程序内存不足或者频繁GC,很有可能存在内存泄露情况,这时候就要借助Java堆Dump查看对象的情况。
    2.要制作堆Dump可以直接使用jvm自带的jmap命令
    3.可以先使用jmap -heap命令查看堆的使用情况,看一下各个堆空间的占用情况。
    4.使用jmap -histo:[live]查看堆内存中的对象的情况。如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉。
    5.也可以使用 jmap -dump:format=b,file=<fileName>命令将堆信息保存到一个文件中,再借助jhat命令查看详细内容
    6.在内存出现泄露、溢出或者其它前提条件下,建议多dump几次内存,把内存文件进行编号归档,便于后续内存整理分析。
    7.在用cms gc的情况下,执行jmap -heap有些时候会导致进程变T,因此强烈建议别执行这个命令,如果想获取内存目前每个区域的使用状况,可通过jstat -gc或jstat -gccapacity来拿到。

    相关文章

      网友评论

          本文标题:05_内存溢出_分析

          本文链接:https://www.haomeiwen.com/subject/vmeuvqtx.html