GC Roots直接引用A和B两个对象,对象B引用C和D两个对象。
1 | // A、C、D未引用其他对象,shallow size和retained size相等 |
在上一种情况的基础上,GC Roots直接引用了对象D。对象D同时被对象B和GC Roots引用。因为D被根直接引用,在对B回收时不会把D当做垃圾进行回收,所以D不算在B的Retained Size内。
1 | // A、C、D未引用其他对象,shallow size和retained size相等 |
分析完理论,我们来做个实验验证下。先看下简单引用的情况
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)
我们对以上代码稍作修改,在创建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