Shallow Size 和 Retained Size
使用过 Eclipse MAT 分析 dump 文件的同学,应该都会见过 Shallow Heap 和 Retained Heap 这两列,稍加留意会发现 Retained Heap 列的数值总是大于等于 Shallow Heap 列的值,那么这两个数值究竟有什么联系和区别呢?
Shallow Size
Shallow Size 为当前对象占用的内存大小,不包括它引用的对象。
Retained Size
Retained Size 为当前对象的大小 + 当前对象 (直接 / 间接) 引用对象的大小。
示例
注: 为方便描述,如下示例使用符号表示对象的 Retained Size 和 Shallow Size。
符号 | 含义 |
---|---|
R(A) | A 对象的 Retained Size |
S(A) | A 对象的 Shallow Size |
1. 简单引用
GC Roots 直接引用 A 和 B 两个对象,对象 B 引用 C 和 D 两个对象。
1 | // A、C、D未引用其他对象,shallow size和retained size相等 |
2. 复杂引用
在上一种情况的基础上,GC Roots 直接引用了对象 D。对象 D 同时被对象 B 和 GC Roots 引用。因为 D 被根直接引用,在对 B 回收时不会把 D 当做垃圾进行回收,所以 D 不算在 B 的 Retained Size 内。
1 | // A、C、D未引用其他对象,shallow size和retained size相等 |
实验
分析完理论,我们来做个实验验证下。先看下简单引用的情况
1. 简单引用实验
1 | /** |
这里我们定义了 B、C、D 三个类,其中 B 包含了 C 和 D 类型的属性。通过不断地往 list 中塞入新创建的对象 B,使得堆溢出出现 OutOfMemory 异常。注意执行这段代码时先设置下 JVM 的参数:**-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError**
使用 Eclipse MAT 打开生成的 dump 文件,切换到 domaintor_tree 界面,查看 B、C、D 对象实例占用的 Shallow Heap 和 Retained Heap 大小
可以看到 C、D 实例的 Shallow Heap 大小和 Retained Heap 大小相等,均为 16
B 的 Retained Heap 大小为 56,Shallow Heap 大小为 24。即 S (B) + S (C) + S (D) = 24 + 16 + 16 = 56 = R (B)
2. 复杂引用实验
我们对以上代码稍作修改,在创建 B 时通过构造函数传入 objectD 的引用
1 | /** |
查看发现 B 的 Retained Set 中已经不包含 D 的实例了,R (B) = 40 = 24 + 16 = S (B) + S (C)
参考
http://supercharles888.blog.51cto.com/609344/1347144
http://blog.csdn.net/kingzone_2008/article/details/9083327
http://bjyzxxds.iteye.com/blog/1532937
预览: