关耳er  

一、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字符串

  

 

 

 

 

 
posted on 2020-03-03 18:09  关耳er  阅读(4590)  评论(0编辑  收藏  举报