首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >糟糕,线上OOM了该怎么办,JVM heap dump快速分析

糟糕,线上OOM了该怎么办,JVM heap dump快速分析

作者头像
架构师修炼
发布2020-07-20 14:33:15
4.7K0
发布2020-07-20 14:33:15
举报
文章被收录于专栏:架构师修炼架构师修炼

前言

在故障定位(尤其是out of memory)和性能分析的时候,经常会用到一些文件辅助我们排除代码问题。这些文件记录了JVM运行期间的内存占用、线程执行等情况,这就是我们常说的dump文件。常用的有heap dump和thread dump(也叫javacore,或java dump)。我们可以这么理解:heap dump记录内存信息的,thread dump记录CPU信息。

概念

heap dump:heap dump文件是一个二进制文件,它保存了某一时刻JVM堆中对象使用情况。HeapDump文件是指定时刻的Java堆栈的快照,是一种镜像文件。

虚拟机:指以软件的方式模拟具有完整硬件系统功能、运行在一个完全隔离环境中的完整计算机系统 ,是物理机的软件实现。常用的虚拟机有VMWare,Visual Box,Java Virtual Machine(Java虚拟机,简称JVM)。

Java虚拟机阵营:Sun HotSpot VM、BEA JRockit VM、IBM J9 VM、Azul VM、Apache Harmony、Google Dalvik VM、Microsoft JVM…

1、为何会内存溢出

内存管理架构

我们知道JVM根据generation(代)来进行GC,根据上图所示,一共被分为young generation(年轻代)、tenured generation(老年代)。

比例分配

绝大多数的对象都在young generation被分配,也在young generation被收回,当young generation的空间被填满,GC会进行minor collection(次回收),速度非常快。其中,young generation中未被回收的对象被转移到tenured generation,当tenured generation被填满时,即触发major collection(FULL GC主回收),整个应用程序都会停止下来直到回收完成。

因此,产生heap dump(内存溢出)错误原因一般出于以下原因:

1)JVM内存过小,

2)程序不严密,

3)产生过多的垃圾无法回收。

2、heapdump文件如何生成?

2.1)使用 jmap 命令生成:

jmap 命令是JDK提供的用于生成堆内存信息的工具,切换到JDK_HOME/bin目录下后,执行下面的命令生成Heap Dump:

windows环境:

jmap -dump:live,format=b,file=heap.hprof <pid>

linux环境:

./jmap -dump:live,format=b,file=heap.hprof <pid>

其中pid是JVM进程的id,heap.hprof是生成的heap dump文件,在执行命令的目录下面。推荐此种方法。

2.2)使用 JConsole 生成

JConsole是JDK提供的一个基于GUI查看JVM系统信息的工具,既可以管理本地的JVM,也可以管理远程的JVM,可以通过下图的 dumpHeap 按钮生成 Heap Dump文件。

JConsole管理控制台

SAP也使用自封装的远程监控jvm服务端口,从而监控jvm运行状态,

在JVM的配置参数中可以添加 -XX:+HeapDumpOnOutOfMemoryError 参数,当应用抛出 OutOfMemoryError 时自动生成dump文件。

3、常见heapdump文件分析工具

3.1)jhat

jhat 是JDK自带的用于分析JVM Heap Dump文件的工具,使用下面的命令可以将堆文件的分析结果以HTML网页的形式进行展示:

jhat <heap-dump-file>

其中 heap-dump-file 是文件的路径和文件名,可以使用 -J-Xmx512m 参数设置命令的内存大小。执行成功之后显示如下结果:

Snapshot resolved. Started HTTP server on port 7000 Server is ready.

这个时候访问 http://localhost:7000/ 即可以看到结果了。

3.2)Eclipse Memory Analyzer(MAT)

Eclipse Memory Analyzer(MAT)是Eclipse提供的一款用于Heap Dump分析的工具,用来辅助发现内存泄漏减少内存占用,从数以百万计的对象中快速计算出对象的 Retained Size,查看并自动生成一个 Leak Suspect(内存泄露可疑点)报表。

相关操作下面将详细进行介绍。

Eclipse Memory Analyzer(MAT):启动打开 File - Open Heap Dump... 菜单,然后选择生成的Heap DUmp文件,选择 "Leak Suspects Report",然后点击 "Finish" 按钮。

内存泄露可疑点报表

第一次打开因需要分析dump文件,所以需要等待一段时间进行分析,分析完成之后dump文件目录下面的文件信息如下:

文件信息

上图中 heap-27311.bin 文件是原始的Heap Dump文件,zip文件是生成的html形式的报告文件。其中zip文件可以直接打开通过网页打开查看概况。

打开如下所示:

主界面

界面常用到功能:

a、Overview(视图):概要界面,显示了概要的信息,并展示了MAT常用的一些功能。

* Details 显示了一些统计信息,包括整 个堆内存的大小、类(Class)的数量、对象(Object)的数量、类加载器(Class Loader)的数量。 * Biggest Objects by Retained Size 使用饼图的方式直观地显示了在JVM堆内存中最大的几个对象,当光标移到饼图上的时候会在左边Inspector和Attributes窗口中显示详细的信息。 * Actions 这里显示了几种常用到的操作,算是功能的快捷方式,包括 Histogram、Dominator Tree、Top Consumers、Duplicate Classes,具体的含义和用法见下面; * Reports 列出了常用的报告信息,包括 Leak Suspects和Top Components,具体的含义和内容见下; * Step By Step 以向导的方式引导使用功能。

b、Histogram(直方图):可以查看每个类的实例(即对象)的数量和大小。

c、Dominator Tree(支配树):列出Heap Dump中处于活跃状态中的最大的几个对象,默认按 retained size进行排序,因此很容易找到占用内存最多的对象。

d、 OQL(MAT提供对象查询语言):跟SQL语言类似,将类当作表、对象当作记录行、成员变量当作表中的字段,通过OQL可以方便快捷的查询一些需要的信息。

e、Thread Overview:查看生成Heap Dump文件的时候线程的运行情况,用于线程的分析。

f、Run Expert System Test:查看分析完成的HTML形式的报告,子菜单项如下图所示:

子菜单项

常用的主要有Leak Suspects和Top Components两种报告: * Leak Suspects :该报告分析了Heap Dump并尝试找出内存泄漏点,最后在生成的报告中对检测到的可疑点做详细的说明; * Top Components :列出占用总堆内存超过1%的对象。

4、案例分析

OOM应用场景:当出现OutofMemory时,将会在相应的目录下生成一份dump文件,而如果不指定选项“XX:HeapDumpPath”,则在当前目录下生成dump文件。在此需要注意,尽管不借助jmap工具,MAT工具也能够直接生成dump文件,但是考虑到生产环境中几乎不可能在线对其进行分析,大都是采用离线分析,因此使用jmap+MAT工具最常见最科学的组合。

当上述程序执行时,必然会触发OutofMemory,然后在所指定的目录下找到生成的dump文件后,我们便可以通过MAT工具来进行分析了。当成功启动MAT后,通过菜单选项“File->Open heap dump...”打开指定的dump文件后,将会生成Overview选项,如图1-1所示:

图1-1 OVERVIEW

在Overview选项中,以饼状图的形式列举出了程序内存消耗的一些基本信息,其中每一种不同颜色的饼块都代表了不同比例的内存消耗情况。如果说需要定位内存泄露的代码点,我们可以通过Dominator Tree菜单选项来进行排查,因此仔细观察和分析才能够找到问题所在),如图1-2所示:

图1-2 支配树排序分析

案例一:

问题现象:客户系统频繁重启,从系统log中发现OOM Error: Server process shutting down with exit code [666]; memory allocation error [OutOfMemoryError],需要通过分析heap dump定位问题原因。

分析过程:查看heap dump中消耗内存大的对象分布情况,总大小:2.7G,其中:有两个大块内存占比大分别:1.7G和376.5M,如下图:

图1-3 内存分布

在Overview选项中,以饼状图的形式列举出了程序内存消耗的一些基本信息。

查看Leak Suspects(内存泄露可疑点)报告分析:

图1-4 泄露可疑点(1)

查看信息初步怀疑与J2EEsession超时检查有关,并涉及Hashtable实例的system class loader类,进一步通过Dominator Tree(支配树)分析定位:

图1-5 分析可疑点(1)

发现有804860条session数存在HashTable中无法被清除,导致无法回收,让开发参与进来确认分析。

图1-6 泄露可疑点(2)

对可疑点(2)分析发现这1.8G也与可疑点(1)状况类似,均是存在Hash Table中一直积累而未清除。

根本原因及解决方案:造成J2EESessionTimeoutChecker中HashTable占用内存过大的原因是在低版本的NetWeaver中session管理不够完善,历史session无法被清除,累积在HashTable中,同时与session相关的信息也被存储在char类型的数组中,无法被回收。建议对NetWeaver进行升级从而完善session管理,避杜绝此类问题再次出现。

链接:https://www.jianshu.com/p/c34af977ade1

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师修炼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念
    • 1、为何会内存溢出
      • 2、heapdump文件如何生成?
        • 3、常见heapdump文件分析工具
          • 4、案例分析
            • 案例一:
        相关产品与服务
        腾讯云 BI
        腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档