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

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

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 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8208 回帖 • 1 关注

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 创业

    你比 99% 的人都优秀么?

    83 引用 • 1398 回帖
  • jsDelivr

    jsDelivr 是一个开源的 CDN 服务,可为 npm 包、GitHub 仓库提供免费、快速并且可靠的全球 CDN 加速服务。

    5 引用 • 31 回帖 • 51 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 473 关注
  • Chrome

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

    62 引用 • 289 回帖
  • 反馈

    Communication channel for makers and users.

    124 引用 • 907 回帖 • 224 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 149 关注
  • 禅道

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

    6 引用 • 15 回帖 • 181 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    41 引用 • 40 回帖
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖 • 1 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 1 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 2 关注
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 606 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 20 关注
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1454 回帖 • 1 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 1 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 724 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 430 关注
  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 232 回帖 • 1 关注
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 196 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 194 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 137 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 600 关注
  • 音乐

    你听到信仰的声音了么?

    60 引用 • 510 回帖
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 555 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    106 引用 • 152 回帖
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    165 引用 • 407 回帖 • 509 关注