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

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

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

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • jsoup

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

    6 引用 • 1 回帖 • 477 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 1 关注
  • 分享

    有什么新发现就分享给大家吧!

    248 引用 • 1792 回帖
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    110 引用 • 54 回帖
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    943 引用 • 943 回帖
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 362 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    12 引用 • 54 回帖 • 65 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    286 引用 • 729 回帖
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    89 引用 • 345 回帖
  • 倾城之链
    23 引用 • 66 回帖 • 136 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 51 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    12 引用 • 54 回帖 • 165 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    266 引用 • 665 回帖
  • SOHO

    为成为自由职业者在家办公而努力吧!

    7 引用 • 55 回帖 • 19 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 588 回帖
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 537 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 628 关注
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 671 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    5 引用 • 26 回帖 • 528 关注
  • DevOps

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

    47 引用 • 25 回帖
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 85 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    85 引用 • 139 回帖 • 1 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 617 关注
  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    86 引用 • 122 回帖 • 625 关注