点击上方 蓝色字体 , 选择 "设为星标"
优质文章, 及时送达
有没有想过 Shallow 和 Retained heap 之间的区别?
Eclipse MAT(内存分析器工具) 是分析 JVM 堆 Dump 文件的强大工具. 当尝试分析内存相关的问题时, 它非常方便. 在 Eclipse MAT 内存分析的报告中会显示对象两种类型的 Heap 信息:
- Shallow Heap
- Retained Heap
在本文中, 我们主要讨论它们之间的区别, 并探讨它们的计算方式.
通过示例理解知识会更容易, 咱们来看看这样一个例子. 例如, 假设你的应用程序具有这样的对象模型, 如图 1 所示:
图 1: 内存中的对象
对象 A 持有对象 B 和 C 的引用.
对象 B 持有对象 D 和 E 的引用.
对象 C 持有对象 F 和 G 的引用.
另外, 我们假设每个对象占用 10 个字节的内存. 在这种场景下, 我们来开始分析吧.
Shallow Heap 大小
请记住: 对象的 Shallow heap 是其自身在内存中的大小 . 由于在我们的示例中, 每个对象占用大约 10 个字节, 因此每个对象的 Shallow heap 大小为 10 个字节. 很简单.
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 大小
咱们再来点更有趣的吧
现在, 让我们的来点更加有趣的吧, 以便让你对 Shallow heap 和 Retained heap 有更加透彻的了解. 在下面的示例中, 让对象 H 开始持有对 B 的引用. 注意对象 B 已经被对象 A 引用了. 现在, 两个家伙 A 和 H 都持有对象 B 的引用. 在这种情况下, 让我们研究 Retained heap 计算将会发生什么变化.
图 3: 新增对 B 的引用
在这种情况下, 对象 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 大小将保持不变, 因为它们的引用没有变化.
希望本文能够让你了解 Eclipse MAT 中的 Shallow heap 大小 和 Retained heap 大小
来源: http://www.tuicool.com/articles/ZJrINvZ