JVM 内存分析 MAT 名词概念

写在前面的话

最近在排查各种性能问题。又用到了好多年没有使用的mat。 问题排查-内存溢出

Heap 名词概念

Eclipse MAT(内存分析器工具)是分析 JVM 堆 Dump 文件的强大工具。当尝试分析内存相关的问题时,它非常方便。在 Eclipse MAT 内存分析的报告中会显示对象两种类型的 Heap 信息:

  • Shallow heap
  • Retained heap

我们主要讨论它们之间的区别,并探讨它们的计算方式。

mat_struct_heap

例如,假设你的应用程序具有这样的对象模型,如图 1 (SH指 shallow heap, b 指的是 byte):
mat_struct_examp_1

图1:内存中的对象

  • 对象 A 持有对象 B 和 C 的引用。
  • 对象 B 持有对象 D 和 E 的引用。
  • 对象 C 持有对象 F 和 G 的引用。

另外,我们假设每个对象占用 10 个字节的内存。在这种场景下,我们开始分析Heap大小的过程。

Shallow Heap

对象的 Shallow heap 是其自身在内存中的大小。说的直白点就是,在没有引用其他对象的情况下本身占用的内存大小,不包括它引用的对象。

  • 针对数组类型(数组或集合)的对象,它的大小是数组元素对象的大小总和。
  • 针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。

由于在我们的示例中,每个对象占用大约 10 个字节,因此每个对象的 Shallow heap 大小为 10 个字节。

Retained Heap

Retained heap: 当对象不再被引用时,垃圾回收器所能回收的总内存,包括对象自身所占据的内存,以及仅能够通过该对象引用到的其他对象所占据的内存: 对象本身的大小 + 引用的其他对象的大小。

换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。

B 的 Retained Heap 大小

从图 1 中,可以注意到对象 B 持有对象 D 和 E 的引用。因此,如果对象 B 是从内存中被垃圾回收,则将不再有对对象 D 和 E 的引用。这意味着此时 D 和 E 也可以被垃圾收集。

Retained heap 指的就是在垃圾回收特定对象时将释放的内存量。

因此,B 的保留堆大小为:= B 的 shallow heap 大小 + D 的 shallow heap 大小 + E 的 shallow heap 大小 = 10 bytes + 10 bytes + 10 bytes = 30 bytes。因此,B 对象的 Retained heap 大小为 30 字节

C 的 Retained Heap 大小

对象 C 拥有对象 F 和 G 的引用。如果对象 C 是从内存中垃圾回收的,将不再持有对对象 F 和 G 的引用。这意味着此时 F 和 G 也可以被垃圾回收。因此,C 的 Retained Heap 大小为:= C 的 shallow heap 大小 + F 的 shallow heap 大小 + G 的 shallow heap 大小 = 10 bytes + 10 bytes + 10 bytes = 30 bytes。因此,C 对象的 Retained heap 大小为 30 字节。

A 的 Retained Heap 大小

对象 A 持有对象 B 和 C 的引用,而对象 B 和 C 又持有对对象 D、E 以及 F、G 的引用。因此,如果对象 A 是从内存中垃圾回收的,则将不再有对 B、C、D、E、F 和 G 对象的引用。

基于此理解,我们来计算下 A 的 Retained Heap 大小。
A 的 Retained Heap 大小为:= A 的 shallow heap 大小 + B 的 shallow heap 大小 + C 的 shallow heap 大小 + D 的 shallow heap 大小 + E 的 shallow heap 大小 + F 的 shallow heap 大小 + G 的 shallow heap 大小 = 10 bytes + 10 bytes + 10 bytes + 10 bytes + 10 bytes + 10 bytes + 10 bytes = 70 bytes。
最后我们可以得出,A 的 Retained heap 大小是 70 字节。

D、E、F、G 的 Retained Heap 大小

D 的 Retained heap 大小与其 Shallow heap 大小相同,就是 10 个字节,因为 D 不持有对任何其他对象的引用。因此,如果 D 获得了垃圾回收,则不会从内存中删除其他的任何对象。同理,E、F 和 G 的 Retained heap 大小也只有 10 个字节。

图 2:对象的 Shallow and Retained Heap 大小(SH指 shallow heap, RH指 Retained heap,b 指的是 byte)
mat_struct_examp_1_total

多一些引用的变数

为了进一步加深对 Shallow heap 和 Retained heap 的理解。在下面的示例中,让对象 H 开始持有对 B 的引用(注意:对象 B 已经被对象 A 引用了)。现在 A 和 H 都持有对象 B 的引用。在这种情况下, Retained heap 计算逻辑将会发生什么变化呢?

图3: 新增对 B 的引用
mat_struct_examp_2_total

在这种情况下,对象 A 的 Retained heap 大小将从之前的 70 减小到 40 个字节。为什么?

如果对象 A 被垃圾回收了,则将仅会影响 C、F 和 G 对象的引用。因此,仅对象 C、F 和 G 将被垃圾回收。

另一方面,由于 H 持有对 B 的活动引用,因此对象 B、D 和 E 将继续存在于内存中。因此,即使 A 被垃圾回收,B、D 和 E 也不会从内存中删除。

于是可以计算出, A 的 Retained heap 大小为:= A 的 shallow heap 大小 + C 的 shallow heap 大小 + F 的 shallow heap 大小 + G 的 shallow heap 大小 = 10 bytes + 10 bytes + 10 bytes + 10 bytes = 40 bytes。

A 的 Retained heap 大小将变为 40 个字节。所有其他对象 Retained heap 大小将保持不变,因为它们的引用没有变化。

其他名词

out going(查看对象为什么消耗内存, 查看对象引用的其他对象)

表示的是当前对象,引用了外部对象

可以使用右键 with outgoing references, 此类对象持有的其他对象。在 Attributes 中可以看到观察对象持有的成员。

in going(查看对象被谁引用)

表示的是当前查看的对象,被外部应用。

可以使用右键 with ingoing references, 其他对象持有的此类对象。

path to GC root (对象没被释放掉的引用)

到GC root的路径

这里有一个特殊的节点GC Roots,这就是reference chain的起点。

Merge Shortest path to GC root (对象没被释放掉的引用)

到GC root的最短路径,右键 merge shortest path to gc root -> exclude all phantim/weak/soft etc. references:查看此对象没被释放掉的原因,只保留强引用。

Histogram

堆内所有类的统计信息,包含类的实例数量和占用的空间。如果此处包含了自己的类就需要注意是否此类创建过多。

默认的大小单位是 Bytes,可以在 Window – Preferences—Memory Analyzer-- 菜单中设置单位。

可以通过filter搜索出自己的类,可以看到内存中共有32049817个Column对象,占用了13GB内存。
mat_struct_Histogram

Dominator Tree

列出了堆中最大的对象,并且引用此对象的其他对象。

mat_struct_Dominator_Tree

如上图,可以很清晰的看到最大的对象是 XXXService @ 0x7fd1752c6f20 这个对象占用了大量内存,次对象被类加载器所引用。

Top Consumers

按类、对象、包分组,列出最消耗资源的类、对象、包。

mat_struct_Top_Consumers

Duplicate Classes

对多个类加载器加载的类进行分析。

Leak Suspects

内存泄漏报告和系统概述

mat_leaks1

Top Components

列出内存用量超过堆总量1%的组件。

References

mat-shallow-heap-retained-heap

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值