Java应用生产Full GC或者OOM问题如何定位

1 引言

生产应用服务频繁Full GC却无法释放内存,甚至可能OOM,这种情况很有可能是内存泄露或者堆内存分配不足,此时需要dump堆信息来定位问题,查看是哪些地方内存泄漏。

Dump文件也称为内存转储文件或内存快照文件,是一个进程或者系统在某一个给定时间的内存快照。例如当进程崩溃或进程出现其它问题时,甚至在任何时候,我们都可以使用工具备份系统或进程的内存进行调试和分析。它包含模块信息、线程信息、堆栈调用信息、异常信息等。

2 查看java服务进程pid

ps -aux|grep java

3 GC简单分析

可使用jdk自带的jstat简单分析一下gc情况

# 每隔 1000毫秒输出一次 jstat -gcutil 1000

输出如下:

----------------------------------------

S0 S1 E O M CCS YGC YGCT FGC FGCT GCT

0.00 66.15 28.84 77.76 93.88 91.90 183 1.058 4 0.517 1.575

0.00 66.15 29.51 77.76 93.88 91.90 183 1.058 4 0.517 1.575

0.00 66.15 30.45 77.76 93.88 91.90 183 1.058 4 0.517 1.575

-----------------------------------------

S0:幸存区survivor0使用百分比

S1:幸存区survivor1使用百分比

E:新生代Eden使用百分比

O:老年代Old使用百分比

M:元数据 Metaspace使用百分比

CCS:压缩类空间Compressed class space使用百分比

YGC:Young GC次数

YGCT:Young GC耗时,毫秒

FGC:Full GC次数

FGCT:Full GC耗时,毫秒

GCT:GC总耗时

2次相邻的GC,可以快速判断那一次GC的耗时;GCT / GC = 平均每次GC耗时

GC是否频繁标准参考:Young GC执行迅速(50毫秒以内)、Young GC执行不频繁(间隔10秒左右一次)、Full GC执行迅速(1秒以内)、Full GC执行不频繁(间隔10分钟左右一次)

如发现Full GC次数频繁增加,Young GC次数不变或变化很小,这就是堆内存不足,很有可能就是内存泄漏的问题。

4 导出dump文件

分析dump文件首先要获取dump文件,获取方法基本有2种

4.1 设置JVM的环境变量

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/xxx.hprof

那在OOM的时候会自动在指定目录生产dump文件,此时只需要在指定目录获取即可

4.2 通过jmap获取

jmap -dump:live,format=b,file=/logs/xxx.hprof 

5 分析dump文件

对于小于自身电脑内存的dump文件,可尝试下载到本地进行分析,可使用的工具有:JVisualVM、JHat、MAT

5.1 使用JVisualVM

在jdk的bin目录下面有JVisualVM,打开它,然后选中文件->装入,选则dump文件,即可

Java应用生产Full GC或者OOM问题如何定位_第1张图片

Java应用生产Full GC或者OOM问题如何定位_第2张图片

点击异常错误的线程:XNIO-1 task-1,等待一会既可以打开堆转储上的线程的指定OOM的地方

Java应用生产Full GC或者OOM问题如何定位_第3张图片

查看具体实例数量和占用大小

点击类 -> 在实例数最多的类名上右击 -> 选择在实例视图中展示 -> 查看引用

Java应用生产Full GC或者OOM问题如何定位_第4张图片

Java应用生产Full GC或者OOM问题如何定位_第5张图片

右键选择在线程中显示,可以查询详情

Java应用生产Full GC或者OOM问题如何定位_第6张图片

5.2 使用jhat

jhat -J-Xmx1024M [file]

执行后等待console中输出Started HTTP on port 7000,看到后就可以通过浏览器访问http://ip:7000了,此页面默认为按package分类显示系统中所有的对象实例。在页面的最下端有Other Queries导航,其中有显示jvm中对象实例个数的链接、有显示jvm中对象大小的链接等,点击显示jvm中对象大小的链接,jhat在分析大的堆dump文件时表现不好,速度很慢。

5.3 使用mat(推荐)

5.3.1 下载

mat下载地址:https://eclipse.dev/mat/previousReleases.php

根据jdk版本下载合适的mat版本,可以通过uname -a命令查看服务器的操作系统版本号

[root@xxx ~]# uname -a
Linux xxxx 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

   使用的是JDK1.8,系统是x86_64,需要选择如下版本:

Java应用生产Full GC或者OOM问题如何定位_第7张图片

5.3.2 解压

unzip MemoryAnalyzer-1.8.0.20180604-linux.gtk.x86_64.zip

5.3.3 修改内存

vi MemoryAnalyzer.ini

5.3.4 文件分析

./ParseHeapDump.sh [hprof文件] org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components

其中hprof文件在实际使用的时候需要替换为hprof文件的路径。运行完毕后在hprof文件所在目录会生成一系列的index/threads文件和3个压缩文件。这3个压缩文件是我们重点关注的分析报告,分别为:

  • xxx_Leak_Suspects.zip:报告包含怀疑造成内存泄漏的地方,报告中包含了class层级图。对于OOM的场景能够很容易的定位到是哪个对象占用了大量内存不释放。
  • xxx_System_Overview.zip:包含heap dump基本信息,dump进程JVM的相关配置和线程信息等。
  • xxx_Top_Components.zip:查看占用空间最大的几个object/class/classloader/package等。报告以饼图和表格的形式展示。通过这个报告可以定位出Java程序运行时哪些对象占用内存较多,对问题排查和程序优化很有帮助。

这三个报告是分析问题的关键。我们通过报告找出内存占用过大的对象,然后结合日志和项目源代码分析程序逻辑,逐步定位出问题。

主要看xxx_Leak_Suspects.zip,解压,打开index.html

Java应用生产Full GC或者OOM问题如何定位_第8张图片

     大部分情况很容易看出问题出现在哪里,当前有时候可能需要进一步分析。

参考资料:

gc 查询java java 查看gc情况_mob6454cc61981e的技术博客_51CTO博客

https://www.cnblogs.com/east7/p/16989436.html

使用Linux的MAT分析工具分析超大dump文件(几GB)_准备起飞55的博客-CSDN博客

Java Heap Dump 分析步骤 - 简书

dump文件过大使用linux mat分析记录_dump文件太大怎么分析-CSDN博客

你可能感兴趣的:(程序员日常,Java,java,开发语言)