一文让你理解什么是shallow heap及retained heap

前言

快速定位性能故障并非一朝一夕之功,需要我们对很多概念有很深刻的理解,在前文中,我们介绍了heap dump的相关概念和其获取方式,今天我们一起来了解一下什么是:
Shallow 和 retained sizes。

GC ROOT是什么?

在java语言中,都是通过可达性分析来判定对象是否存活的。此算法的基本思路是:通过一系列的称为“GC Roots”的对象作为起点,从这些节点向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连,则证明此对象是不可达的。

file

在上图右侧中,我们可以看到,对象5/6/7虽然有依赖关联,但是他们到GC ROOT根节点是不可达的,所以这三个节点对象会被判定为是可回收的。

GC ROOT的定义比较特别,他们不属归属于对象图中,对象也不能反向的依赖他们,这也确保了不会出现循环引用的问题。因此也容易得出,只有引用类型的变量才被认为是Roots,值类型的变量永远不被认为是Roots。

在Java中,可作为GC Roots的对象包括以下几种:

虚拟机栈(栈帧中的局部变量表,Local Variable Table)中引用的对象。
方法区中类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI(即一般说的Native方法)引用的对象。

看到这里你可能要问,选择这些对象的依据是什么呢?

首先,GCROOT的目标对象是要以当前还在存活的对象集合,因此必须要选取确定存活的引用类型对象,GC管理的区域是java的堆,虚拟机栈、方法区和本地方法栈不被GC所管理,因此选用这些区域内引用的对象作为GC Roots,是不会被GC回收的。

其中虚拟机栈和本地方法栈都是线程私有的内存区域,只要线程没有终止,就能确保它们中引用的对象的存活。而方法区中类静态属性引用的对象是显然存活的。常量引用的对象在当前可能存活,因此,也可能是GC roots的一部分。

下图是使用MAT工具中的 “path to GC roots ”功能分析出来的引用链。
file

它标识从当前对象到GC roots的路径,这个路径解释了为什么当前对象还能存活,对分析内存泄露很有帮助。

在查询到GC root的路径时,默认是包含所有引用的,从GC角度说,一个对象无法被GC,一定是因为有强引用存在,其它引用类型在GC需要的情况下都是可以被GC掉的,所以这里我使用 exclude all phantom/weak/soft etc. references 只查看GC路径上的强引用。

shallow heap和retained heap

直译过来是浅层堆和保留堆的意思。先说一说其基本的概念。

shallow heap

表示对象本身占用内存的大小,也就是对象头加成员变量(不是成员变量的值)的总和。

如一个引用占用32或64bit,一个integer占4bytes,Long占8bytes等。

如简单的一个类里面只有一个成员变量int i,那么这个类的shallow size是12字节,因为对象头是8字节,成员变量int是4字节。

常规对象(非数组)的Shallow size有其成员变量的数量和类型决定,数组的shallow size有数组元素的类型(对象类型、基本类型)和数组长度决定。

对象的值是分配给存储对象本身的内存量,不考虑所引用的对象。常规(非数组)对象的浅大小取决于其字段的数量和类型。数组的浅尺寸取决于数组的长度及其元素(对象、基本类型)的类型。一组对象的浅尺寸表示该集合中所有对象的浅尺寸之和。

retained heap

如果一个对象被释放掉,那会因为该对象的释放而减少引用进而被释放的所有的对象(包括被递归释放的)所占用的heap大小,即对象被垃圾回收器回收后能被GC从内存中移除的所有对象之和。相对于shallow heap,Retained heap可以更精确的反映一个对象实际占用的大小(若该对象释放,retained heap都可以被释放)。

实际案例分析

file

正如上图所示:
在这两张图中,我们画出了GC ROOT到所有对象引用链。在这里我们着重分析一下Retained size。

对于obj1这个对象:
GC ROOT指向它,并且它依赖于obj2、obj3、obj4,但是由于obj3同样也被GC ROOT所指。
所以:

分析obj1:

对于图1,retained size包括:obj1+obj2+obj4

对于图2,retained size包括:obj1+obj2+obj3+obj4

分析obj2:

对于图1:retained size包括:obj2+obj4

对于图2:retained size包括:obj2+obj3+obj4

总结

本篇文章围绕内存分析中的Shallow 和Retained heap扩展了解了几个知识点如下:

  • gc root的定义和概念的了解。
  • 对象可达性分析和选择gc root的依据。
  • 针对单个对象使用“path to GC roots”查看其引用树。
  • shallow heap和retained heap的基本概念。

创建了一个java方面的互助群,和其他传统的学习群不同。
在本群,你可以
1)阐述你在开发过程中遇到的问题,群友集思广益,高效解答。
2)分享自己学习的一些心得,让后来学习者少踩坑。
3)资源共享,无论是好的学习视频还是文档都可以在群内共享。
别人有可能可以给你提供一些思路和看法
同样,如果你也乐于帮助别人,那解决别人遇到的问题,也同样对你是一种锻炼。

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值