• jmap的使用以及内存溢出分析


    一、jmap的使用以及内存溢出分析

      前面通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容,如:内存使用情况的汇总、对内存溢出的定位与分析

    1、查看内存使用情况

    jmap -heap 29720

      

    2、查看内存中对象数量及大小  

       #查看所有对象,包括活跃以及非活跃的  jmap ‐histo <pid> | more
      #查看活跃对象  jmap ‐histo:live <pid> | more
    #查看活跃对象
    jmap -histo:live 29720 | more
      
      对象说明:
        B byte
        C char
        D double
        F float
        I int
        J long
        Z boolean
        [ 数组,如[I表示int[]
        [L+类名 其他对象

    3、将内存使用情况dump到文件中

      有些时候我们需要将jvm当前内存中的情况dump到文件中,然后对它进行分析,jmap也是支持dump到文件中的。
    #用法: jmap -dump:format=b,file=dumpFileName <pid>
    jmap -dump:format=b,file=../tmp/dump.dat 29720
      

       

    4、通过jhat对dump文件进行分析

      我们将jvm的内存dump到文件中,这个文件是一个二进制的文件,不方便查看,这时我们可以借助于jhat工具进行查看。
    #用法: jhat -port <port> <file>
    jhat -port 29729 ../tmp/dump.dat
      打开浏览器进行访问:http://localhost:29729/
      
      在最后面有OQL查询功能:

       

      点击下面选项:

      

       进入页面,输入下面语句查询字符串大于10000,点击Execute按钮,查询结果:

    select s from java.lang.String s where s.value.length >= 10000

      

    5、通过MAT工具对dump文件进行分析 

    5.1  MAT工具介绍

      MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象。

    5.2  下载安装  

     
      

      解压后得到的文件列表:

       

    5.3  使用

      ①双击启动 MemoryAnalyzer.exe应用程序

        

      ②打开一个dump文件

         

      ③操作如图两步

        

      ④查看Overview

         

      ⑤查看Histogram

        

      ⑥查看对象以及它的依赖  dominator_tree

         

      ⑦查看可能存在内存泄露的分析

          

    二、内存溢出的定位与分析 

      内存溢出在实际的生产环境中经常会遇到,比如,不断的将数据写入到一个集合中,出现了死循环,读取超大的文件等等,都可能会造成内存溢出。
    如果出现了内存溢出,首先我们需要定位到发生内存溢出的环节,并且进行分析,是正常还是非正常情况,如果是正常的需求,就应该考虑加大内存的设置,如果是非正常需求,那么就要对代码进行修改,修复这个bug。
      首先,我们得先学会如何定位问题,然后再进行分析。如何定位问题呢,我们需要借助于jmap与MAT工具进行定位分析。 

    1、模拟内存溢出 

      编写代码,向List集合中添加100万个字符串,每个字符串由1000个UUID组成。如果程序能够正常执行,最后打印ok
    package com.zn;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;
    
    public class TestJvmOutOfMemory {
        public static void main(String[] args) {
            List<Object> list = new ArrayList<>();
            for (int i = 0; i < 10000000; i++) {
                String str = "";
                for (int j = 0; j < 1000; j++) {
                    str += UUID.randomUUID().toString();
                }
                list.add(str);
            }
            System.out.println("ok");
        }
    }

    2、设置VM options参数  

    -Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
      

    3、运行测试

      

    4、当发生内存溢出时,会dump文件到java_pid65828.hprof

       

    5、导入到MAT工具中进行分析

      
      可以看到,有87.99%的内存由Object[]数组占有,所以比较可疑。
      分析:这个可疑是正确的,因为已经有超过90%的内存都被它占有,这是非常有可能出现内存溢出的。

    6、查看详情 

      可以看到集合中存储了大量的uuid字符串

      

     
  • 相关阅读:
    APP切换环境
    Cors
    有关JavaScript事件循环的若干疑问探究
    你知道async await的缺陷吗?
    Referrer Policy示例讲解
    HSTS 示例讲解
    解决element ui的zindex问题
    js加载在css前面或后面的示例讲解
    window.name和postMessage跨域详解
    clickjacking的示例讲解
  • 原文地址:https://www.cnblogs.com/Zzzzn/p/12403764.html
Copyright © 2020-2023  润新知