使用 Memory Analyzer(MAT) 定位内存溢出 / 泄漏

本贴最后更新于 1904 天前,其中的信息可能已经物是人非

Memory Analyzer 是什么

 Memory Analyzer(MAT)是由 eclipse 提供的一款可视化 java 堆分析器,可以快速帮你查找内存泄漏并减少内存消耗,它提供了可视化的报告并可以查看堆文件中各个对象的信息。官网下载链接

什么时候用 MAT

 当线上的某个 service/微服务老莫名其妙的崩掉或者出现莫名问题,当你需要对不熟悉的代码进行调优,当内存溢出/泄漏且代码量巨大的时候。因为 MAT 的可视化,你很容易就能把堆文件里面对应的大对象找出来,随之可以快速的定位大对象对应的代码处进行查看。

MAT 实践

1) 内存溢出

  /**
   * 测试内存溢出 
   */
  public class TestHeapSpace {

	public static void main(String[] args) throws Exception{
	  getLines("/Users/yangjunwei/data/test/HNP_StatsFootNot.csv").forEach(x-> System.out.println(x));
	}

    /**
	 * 返回文件的内容 * @param file
	 * @return
	 * @throws Exception
    */  
	private static List getLines(String file) throws Exception{
	  BufferedReader reader = null;
	  List list = new ArrayList<>();
	  try{
		reader = new BufferedReader(new FileReader(new File(file)));
		String tmp =null;
		while ((tmp = reader.readLine()) != null){
		  list.add(tmp);
		}
	  }finally {
		if( reader != null ){
		  reader.close();
		}
	  }
	  return list;
	}
  }

 上面是一个读取文件内容的例子,乍一看问题不大,但文件内容过多,执行内存不是太大的情况下会发生什么?

  ll -h /Users/yangjunwei/data/test/HNP_StatsFootNot.csv
  22M  1 25 13:06 /Users/yangjunwei/data/test/HNP_StatsFootNot.csv
  
  // 模拟内存溢出,限定该程序最大堆内存为10M,因为文件内容为22M,10M必然加载不了22M的文本信息,所以就发生了内存溢出异常并导出了堆文件(启动参数加了-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath)。
  java -jar -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath='/Users/yangjunwei/data/test/head_outMemory.hprof' -Xmx10M yy_test_heap_outMemory.jar
  java.lang.OutOfMemoryError: Java heap space
  Dumping heap to /Users/yangjunwei/data/test/head_outMemory.hprof ...
  Heap dump file created [10782477 bytes in 0.064 secs]
  Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOfRange(Arrays.java:3664)
	at java.lang.String.<init>(String.java:207)
	at java.io.BufferedReader.readLine(BufferedReader.java:356)
	at java.io.BufferedReader.readLine(BufferedReader.java:389)
	at com.winasdaq.yy_test.TestHeapSpace.getLines(TestHeapSpace.java:32)
	at com.winasdaq.yy_test.TestHeapSpace.main(TestHeapSpace.java:15)
  ll -h /Users/yangjunwei/data/test/head_outMemory.hprof
  10M  2  1 15:44 /Users/yangjunwei/data/test/head_outMemory.hpro

 下来咱们就用 MAT 来分析一下这个 10M 的堆文件
 1.1 打开要分析的堆文件

 1.2 选择 LEAk REPORT

 1.3 LEAk REPORT 的饼图(由这个饼图发现有一个问题,有一个大对象占了 8.7M 的内存)

 1.4 揪出这个大对象

 1.5 定位问题
 发现那个大对象是一个 ArrayList,并占了百分之 97 的内存。这个对象的里面的记录正是文本的一行行记录。
2) 内存泄漏
 如果上述代码申请了足够的内存且在一个 webservice 里面,把下面代码代码注释掉就会发生内存泄漏。

 if( reader != null ){
	reader.close();
 }

 当一个对象失去所有的引用的时候,在 GC 的时候,就可以将其回收,反之则不回收,因为 reader 里面加载了文件的内容还没有关闭,所以它不会被 GC 回收,一个泄漏不可怕,多次泄漏之后堆内存里面会存放大量的不能被 GC 回收的对象,最终会导致于把内存撑爆,发生内存溢出的情况。用 MAT 实践同样能定位到问题,这里就不做赘述。
堆文件导出
 1)被动导出,上面测试内存溢出的范例中已有,启动参数加上(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPat)即可,这种情况只是在内存溢出的时候才会被动导出堆文件
 2)利用 jdk 的工具 jmap 把堆文件主动导出(openjdk 的话要另外安装 openjdk-devel 包)

  $ ./jmap
  Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

  where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system

 先 ps -ef|grep java,把需要导出的 java 的 pid 找出来,然后通过 jmap 命令导出

  // 导出pid为1151的堆文件,格式2进制,导出文件为/Users/yangjunwei/data/test/1151.hprof
  ./jmap -dump:format=b,file='/Users/yangjunwei/data/test/1151.hprof' 1151
  Dumping heap to /Users/yangjunwei/data/test/1151.hprof ...
  Heap dump file created
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3167 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • FFmpeg

    FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

    22 引用 • 31 回帖 • 3 关注
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 250 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    207 引用 • 2031 回帖
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    5 引用 • 15 回帖 • 223 关注
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    19 引用 • 31 回帖 • 3 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    238 引用 • 224 回帖 • 1 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 640 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 36 关注
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖 • 1 关注
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    324 引用 • 1395 回帖 • 3 关注
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    60 引用 • 287 回帖 • 2 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 404 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    185 引用 • 318 回帖 • 348 关注
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 19 关注
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    51 引用 • 190 回帖 • 2 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    38 引用 • 24 回帖
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    1 引用 • 11 回帖 • 1 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 6 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    476 引用 • 899 回帖
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    131 引用 • 3639 回帖
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    535 引用 • 672 回帖 • 2 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 243 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 593 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    395 引用 • 3408 回帖
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    368 引用 • 1212 回帖 • 576 关注
  • 电影

    这是一个不能说的秘密。

    120 引用 • 597 回帖 • 1 关注