文章目录
本文讲解如何生成堆存储文件,并分析堆文件中异常的大对象,及其相关调用链等,可以定位出内存泄露、内存溢出等问题。
本文关键词:
一. 相关命令
1. 查看进程堆内存整体使用情况:OOM的可能
jmap -heap 8179
Attaching to process ID 8179, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.92-b14
using thread-local object allocation.
Garbage-First (G1) GC with 18 thread(s)
Heap Configuration: #堆内存初始化配置
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 536870912 (512.0MB)
NewSize = 1363144 (1.2999954223632812MB)
MaxNewSize = 321912832 (307.0MB)
OldSize = 5452592 (5.1999969482421875MB)
NewRatio = 2 #-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
SurvivorRatio = 8 #-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 1048576 (1.0MB)
Heap Usage:
G1 Heap:
regions = 512
capacity = 536870912 (512.0MB)
used = 347981816 (331.86132049560547MB)
free = 188889096 (180.13867950439453MB)
64.81666415929794% used
G1 Young Generation:
Eden Space:
regions = 265
capacity = 304087040 (290.0MB)
used = 277872640 (265.0MB)
free = 26214400 (25.0MB)
91.37931034482759% used
Survivor Space:
regions = 33
capacity = 34603008 (33.0MB)
used = 34603008 (33.0MB)
free = 0 (0.0MB)
100.0% used
G1 Old Generation:
regions = 35
capacity = 198180864 (189.0MB)
used = 35506168 (33.86132049560547MB)
free = 162674696 (155.13867950439453MB)
17.916042590267445% used
30742 interned Strings occupying 3947896 bytes.
这里看到Survivor Space(幸存者空间)已经被100.0%使用
2. 统计类的对象数量以及内存占用:定位内存泄漏
## 查看活着的对象
jmap -histo:live 8179
num #instances #bytes class name
----------------------------------------------
1: 92285 14964792 [C
2: 90345 2168280 java.lang.String
3: 57918 1853376 java.util.concurrent.ConcurrentHashMap$Node
4: 15970 1758272 java.lang.Class
5: 5369 1673712 [B
6: 16297 1434136 java.lang.reflect.Method
7: 25573 1432088 java.util.LinkedHashMap
...
6217: 1 16 sun.util.locale.provider.SPILocaleProviderAdapter
6218: 1 16 sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter
6219: 1 16 sun.util.resources.LocaleData
6220: 1 16 sun.util.resources.LocaleData$LocaleDataResourceBundleControl
Total 700466 41856208
针对每个占用大量内存的对象,分析其引用链,即它所引用的其他对象和被其他对象引用的情况。这有助于确定对象何时被创建,以及是否有引用导致它们不能被垃圾回收。
二. 分析内存占用
1. 使用 jhat 排查对象堆占用情况
1.1. 排查步骤
第一步:导出堆文件
jmap -dump:file=<file_name> <pid>
第二步:分析堆文件
生成文件后执行
jhat heap_dump.hprof
Reading from heap_dump.hprof...
Dump file created Mon Mar 05 18:33:10 CST 2024
Snapshot read, resolving...
Resolving 751016 objects...
Chasing references, expect 150 dots......................................................................................................................................................
Eliminating duplicate references......................................................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
第三步:查看html
对于jhat启动后显示的html页面中功能:
一般查看堆异常情况主要看这个两个部分
- Show instance counts for all classes (excluding platform),平台外的
所有对象信息
。
- Show heap histogram 以树状图形式展示
堆情况
。
1.2. 具体分析例子
a. 分析频繁创建对象导致的OOM
可以看到bson相关有几十万个实例,alarmMessage有十几万个实例,也就是说alarmMessage被频繁创建。接着分析:
1.3. OQL查看某一个对象的引用情况
对于大对象排查内存溢出的可能,我们打开OQL窗口看对象中的value是否为null,执行如下OQL语句
select u from com.webank.wedatasphere.linkis.common.ServiceInstance u where (u.value = null)
如果当value=null时,仍然有强引用存在,此时gc是不能回收的,这样就会出现内存的溢出问题。
如下图,我们可以点击查看某个对象,可以看到如下成员变量、引用的对象、其他弱引用。
更多关于对象查询语言可参考:jhat中的OQL(对象查询语言)
2. 使用jvisualvm
在mac控制台下输入
jvisualvm
装入快照
分析:对象数与堆占用
查看对象被引用的关系
3. MAT分析ing
可参考:https://gitcode.csdn.net/65e6e3871a836825ed786d51.html