zoukankan      html  css  js  c++  java
  • JVM内存溢出分析java.lang.OutOfMemoryError: Java heap space

    JVM内存溢出查询java.lang.OutOfMemoryError: Java heap space查出具体原因分为几个预备步骤

    1、在运行java程序是必须设置jvm

      -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump_OOME.hprof    当内存溢出时 会输出在/tmp/dump_OOME.hprof目录下

    #jvm options
    #JAVA_OPTS="-Xms8192m -Xmx8192m -Xmn4096m -Djava.awt.headless=true -XX:MaxPermSize=512m -server -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=85 -XX:+DisableExplicitGC -Xnoclassgc -Xverify:none"
    JAVA_OPTS="-Xms4096m -Xmx4096m -Djava.awt.headless=true -XX:MaxPermSize=512m -server -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=85 -XX:+DisableExplicitGC -Xnoclassgc -Xverify:none"
    JAVA_OPTS="$JAVA_OPTS -javaagent:/usr/local/src/sflowagent.jar -Dsflow.hostname=platform -Dsflow.dsindex=10000"
    JAVA_OPTS="$JAVA_OPTS -XX:+PrintGC -XX:+PrintGCDateStamps  -XX:+PrintGCDetails -Xloggc:/tmp/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M"
    JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump_OOME.hprof"

    2、可以在eclipse安装分析dump_OOME.hprof 的插件MemoryAnalyzerTool

        MemoryAnalyzerTool(也叫MAT)是一款JAVA虚拟机内存映像分析工具,

        可以在JAVA程序运行的时候有程序抛出的异常加上已经设置好的参数(-XX:+HeapDumpOnOutOfMemory)调试出内存泄漏或者异常的位置以及原因跟踪

        MemeoryAnalyzer可以对Dump出来的堆转储快照进行分析,重点是确认内存中的对象是否是有必要的,也就是要先确认到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory OverFlow)

      

        运行Eclipse,然后单击菜单栏上“Help=》Install New Software...”

        进入软件源导入界面,你可以选择使用URL直接导入,URL导入的地址为:

    http://download.eclipse.org/mat/1.7/update-site/

          但是由于镜像连接不稳定性,我使用的是下载压缩包zip然后安装,压缩包下载地址为:http://ftp.jaist.ac.jp/pub/eclipse/mat/1.7/MemoryAnalyzer-1.7.0.201706130745.zip

        下载完成之后将其导入,"Add》Archive》选择你下载好的zip文件》OK":

      确定之后勾选"Memory Analyzer for Eclipse IDE"下面的两项即可,这个是用于Eclipse内部使用的插件,下面一个“Stand-alone Memory Analyzer“是独立的分析工具,一般不用勾选。

      之后单击“Next"等待一段时间Eclipse计算的需求和依赖文件下载完毕后,一路"next",并接受协议“Finish”即可完成安装,重启Eclispe后就可以使用MAT了。

    3、使用Memory Analyzer 分析内存溢出

      

    1.设置JVM参数

      JVM的参数可以用于调试JVM在各种限制条件下的常见BUG,一下简单介绍几个参数:

    -XX:+HeapDumpOnOutOfMemoryError    //虚拟机在堆异常时生成对存储快照,后缀一般是.hprof
    -Xms    //Java堆的最小值,例如-Xms20m,将Java堆的最小值设置为20MB
    -Xmx    //Java堆的最大值,例如-Xms40m,将Java堆的最大值设置为40MB

      了解了参数之后,可以对参数进行一定的设置,以便我们简单的对MAT工具进行使用测试,设置参数如下:

    -XX:+HeapDumpOnOutOfMemoryError
    -XX:HeapDumpPath=D://dump_OOME.hprof -Xms20m -Xmx20m

      之所以将最小和最大的堆设置为一样是为了能避免堆的自动扩展,以及20MB的空间是为了让程序能尽快的占满使得内存溢出。

      设置JVM的启动参数可在“Run》Run Configuration》Arguments》Vm arguments”中填写

    2.编写内存溢出(Memory Leak)代码

      思路:通过新建集合列表List,然后以while(true)死循环的方式使得List集合不断添加新的对象,使得其不断地占满堆空间

      代码:

    复制代码
    package com.study;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class TestStudy {
    
        static class OOMClass { }
        
        public static void main(String[] args) {
            List<OOMClass> list = new ArrayList<OOMClass>();
            while(true) {
                list.add(new OOMClass());
            }
        }
    
    }
    复制代码

      执行代码,发现输出如下:

      注意到“java_pid24792.hprof”文件,这个文件是JVM生成的对存储快照,之后可以通过MAT工具打开,进行分析追踪,这个文件将自动保存到你的Eclipse workspace下的工作目录中,以我的为例:

    3.打开MAT的Perspective

      由于MAT工具需要另外打开一个工作视图(就像Eclipse EE和Java的切换视图一样),因此需要在先配置打开"Window》Perspective》Open Perspective》Other...":

      选择Memory Analysis并确定:

      完后之后将进入MAT的工作空间视图,你可以在Eclipse右上角进行切换回Java或者EE,由于接下来要使用MAT分析,因此就暂时不切回之前的Java了

    4.打开需要分析的堆转储快照.hprof文件

      由于MAT是依赖于生成的堆转储快照,而不是在运行的时候自动捕获,因此,再确认进入MAT的工作空间后,点击"File》Open Heap Dump》选择刚生成的“java_pid24792.hprof”文件,一直默认就可以查看内存问题的分析图表以及GC根

      你可以进行一些分析操作,可以看到Action下的几个选项:

      a.Histogram:列出每个类的实例列表;

      b.Dominator:列出最大的对象和他们存在的东西;

      c.Top Comsumer:打印按类和包分组的最昂贵的对象;

      d.Duplicate Classes:检测由多个类加载器加载的类。

    5.使用MAT找出问题存在的对象

      由于是一个简单的问题,因此我们直接选择Dominator,可以直接以百分比的形式打印出对象所占的百分比,一般的内存溢出大部分情况都是有某一个对象过多存在而未被GC回收导致,所以可以点开最大百分比的类一级级找,不难找到问题所在:

      可以看到列出额其中的25条,还有810300条目未列出,这81万个对象占据了97.36%的堆空间,因此不难发现是OOMClass类的对象生成过多为未被回收导致内存溢出。

    6.进一步追踪问题源并进行定位

      在"default_report org.eclipse.mat.api:suspects"的标签分页中

      在"Program Suspect 1》Details"点击后找到"Thread Stack"中追踪出错点

      看到出错点在第13行,找到对应的Java代码TestStudy的13行:

    复制代码
     1 package com.study;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 public class TestStudy {
     7 
     8     static class OOMClass { }
     9     
    10     public static void main(String[] args) {
    11         List<OOMClass> list = new ArrayList<OOMClass>();
    12         while(true) {
    13             list.add(new OOMClass());
    14         }
    15     }
    16 
    17 }
    复制代码

      找到了追踪的出错位置,以上就是使用Memory Analyzer工具完成的堆栈分析。

  • 相关阅读:
    vue-fullcalendar插件
    iframe 父框架调用子框架的函数
    关于调试的一点感想
    hdfs 删除和新增节点
    hadoop yarn 实战错误汇总
    Ganglia 安装 No package 'ck' found
    storm on yarn(CDH5) 部署笔记
    spark on yarn 安装笔记
    storm on yarn安装时 提交到yarn失败 failed
    yarn storm spark
  • 原文地址:https://www.cnblogs.com/lemon-flm/p/11599505.html
Copyright © 2011-2022 走看看