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

news/2024/12/22 0:06:18/

前言

快速定位性能故障并非一朝一夕之功,需要我们对很多概念有很深刻的理解,在前文中,我们介绍了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)资源共享,无论是好的学习视频还是文档都可以在群内共享。
别人有可能可以给你提供一些思路和看法
同样,如果你也乐于帮助别人,那解决别人遇到的问题,也同样对你是一种锻炼。


http://www.ppmy.cn/news/300997.html

相关文章

Spark是什么?

Spark是个通用的集群计算框架,通过将大量数据集计算任务分配到多台计算机上,提供高效内存计算。如果你熟悉Hadoop, 那么你知道分布式计算框架要解决两个问题:如何分发数据和如何分发计算。Hadoop使用HDFS来解决分布式数据问题&…

【Spark】Spark是什么?能干什么?有什么特点?

一、什么是Spark 官网:http://spark.apache.org Apache Spark™ is a multi-language engine for executing data engineering, data science, and machine learning on single-node machines or clusters. Spark是一种快速、通用、可扩展的大数据分析引擎&#xf…

SharpPcap 开发笔记

原文地址: http://blog.chinaunix.net/u/884/showart_2281574.html 由于项目的需要,要从终端与服务器的通讯数据中获取终端硬件状态,所以用到了广为流传的C#抓包库SharpPcap。 SharpPcap目前最新版本是3.1.0,基于.Net 3.5和WinPc…

Pulsar 各个Shedder分析及新的Shedder -- AvgShedder

看到今年Pulsar 峰会上挺多人分享负载均衡的内容,这里也整理分享一下相关的内容。 社区现有策略的分析 LoadSheddingStrategy pulsar进行shedding的时候,使用的是ThresholdShedder类,ThresholdShedder类是LoadSheddingStrategy接口的其中一…

基于 shapley-value 的可解释方法及 shap 库实现

一. 为什么需要可解释 几点考虑: 若模型完全黑箱, 会有信任风险, 虽然 Performance 不错, 但在医学诊断等严肃领域, 同样要关心诊断依据.人类天生的好奇心, 也想知道不同特征到底作了怎样的贡献.对模型预测的 badcase 作诊断, 增强洞察, 辅助模型与特征的迭代. 模型可解释其…

理解Sharpe夏普比率与Python实现

风险与收益 基金绩效评价标准化指标。 风险的大小在决定组合的表现上具有基础性的作用; 风险调整后的收益率,就是一个可以同时对收益与风险加以考虑的综合指标,以期能够排除风险因素对绩效评估的不利影响。 夏普比率的核心思想 理性的投资者…

模型解释性:SHAP包的使用

本篇博客介绍另一种事后可解释性方法:SHAP(SHapley Additive exPlanation)方法。 1. Shapley值理论 Shapley值是博弈论中的一个概念,通过衡量联盟中各成员对联盟总目标的贡献程度,从而根据贡献程度来进行联盟成员的利益分配,避免…

SHAP解释模型(二)

本文在SHAP解析模型之后,又尝试了一些SHAP新版本的进阶用法,整理并与大家分享. 1 环境配置 以下实验使用当前最新版本shap:0.41.0,同时安装xgboost作为预测模型,并使用较高版本的matplotlib(低…