理解Heap Profling名词-Shallow和Retained Sizes

本文详细解析了HeapProfiling工具中ShallowSize与RetainedSize的概念。ShallowSize指对象自身占用内存大小,不包含其引用的对象;RetainedSize则为对象及其所有直接或间接引用对象的总大小。通过示例图进一步阐述了这两个概念的实际应用。

所有包含Heap Profling功能的工具(MAT, Yourkit, JProfiler, TPTP等)都会使用到两个名词,一个是Shallow Size,另一个是 Retained Size.
这是两个在平时不太常见的名词,本文会对这两个名词做一个详细的解释。

Shallow Size
对象自身占用的内存大小,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。
针对数组类型的对象,它的大小是数组元素对象的大小总和。

Retained Size
Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C, C就是间接引用)
换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。
不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。

看图理解Retained Size


上图中,GC Roots直接引用了A和B两个对象。

A对象的Retained Size=A对象的Shallow Size
B对象的Retained Size=B对象的Shallow Size + C对象的Shallow Size

这里不包括D对象,因为D对象被GC Roots直接引用。
如果GC Roots不引用D对象呢?

此时,
B对象的Retained Size=B对象的Shallow Size + C对象的Shallow Size + D对象的Shallow Size

转载请注明原文链接:http://kenwublog.com/understand-shallow-and-retained-size-in-hprofling

<think> 我们被要求解释 shallow heap retained heap 的含义、区别及应用。 引用[1][2][3][4]提供了相关定义示例。下面将结合这些引用进行说明,并注意格式要求(数学表达式用$...$或$$...$$,中文回答,生成相关问题)。 ### 1. Shallow Heap(浅堆)的含义 Shallow Heap 是指**对象自身占用的内存大小**,不包括它引用的对象[^2][^4]。具体来说: - **非数组对象**:其大小为对象本身及其所有成员变量的大小总,包括Java对象头(Object Header)等语言特性所需的数据存储单元。 - **数组对象**:其大小为所有数组元素占用内存的总(注意:对于引用类型数组,数组元素存储的是引用,实际对象的大小不计入)。 数学表达: 设对象$O$的Shallow Heap为$S(O)$,则: $$S(O) = \text{对象头大小} + \sum_{i=1}^{n} \text{成员变量}_i\text{的大小}$$ 对于数组,若元素类型为基本类型,则: $$S(O) = \text{数组对象头} + \text{数组长度} \times \text{元素类型大小}$$ ### 2. Retained Heap(保留堆)的含义 Retained Heap 是指**当该对象被垃圾回收(GC)后,可以释放的堆内存总量**[^2][^3][^4]。它包含两部分: 1. 对象自身的Shallow Heap。 2. 该对象**直接或间接引用**的所有对象的Shallow Heap,但需排除: - 被GC Roots直接或间接引用的对象(这些对象不会被回收)。 - 被其他未被回收对象引用的对象(即只被该对象引用的对象链才会被计入)。 数学表达: 设对象$O$的Retained Heap为$R(O)$,则: $$R(O) = S(O) + \sum_{A \in \text{Uniquely Reachable from } O} S(A)$$ 其中“Uniquely Reachable”指仅通过$O$可达且不受GC Roots保护的对象。 ### 3. 区别与联系 | **特性** | **Shallow Heap** | **Retained Heap** | |----------------|-------------------------------------------|--------------------------------------------| | **计算范围** | 仅自身内存 | 自身 + 独占引用的对象链内存 | | **GC意义** | 回收单个对象释放的内存 | 回收该对象及其独占对象链释放的总内存 | | **依赖关系** | 独立于引用结构 | 依赖于对象引用关系 | | **典型应用** | 分析单个对象内存占用 | 分析内存泄漏(识别持有大量内存的对象) | #### 示例解析(引用[2][4]的图示案例): 假设GC Roots直接引用对象$A$$B$: ``` GC Roots │ ├── A └── B │ └── C │ └── D ``` - **$A$的Retained Heap**:仅$S(A)$(因为$A$无引用其他对象)。 - **$B$的Retained Heap**:$S(B) + S(C)$($D$被GC Roots直接引用?引用[2][4]指出,若$D$被GC Roots直接引用,则不计入$B$的Retained Heap)。 - 修正:引用[4]明确说明,若GC Roots**不引用$D$**,则$B$的Retained Heap为$S(B)+S(C)+S(D)$[^4]。 ### 4. 应用场景 1. **内存泄漏分析**: - **Retained Heap**用于定位“内存黑洞”对象。例如,MAT的“Dominator Tree”视图按Retained Heap排序,帮助找出持有最大无效内存的对象[^1]。 - 对比:Shallow Heap大的对象未必是泄漏点(如缓存对象),但Retained Heap大的对象更可能是泄漏源。 2. **优化内存使用**: - Shallow Heap帮助识别基础类型(如`int[]`)或轻量级对象的内存开销。 - Retained Heap揭示对象删除后可释放的总内存,指导代码优化(如断开无用引用链)。 3. **垃圾回收效率**: - Retained Heap大小直接影响GC效率。大量Retained Heap高的对象会导致GC停顿时间延长。 ### 5. 在MAT中的实操示例 在Eclipse Memory Analyzer (MAT)中: - **Histogram视图**:默认显示Shallow Heap,可切换为Retained Heap列。 - **Dominator Tree视图**:以Retained Heap排序,展示对象对内存的“控制权”[^1]。 - **Path to GC Roots**:分析Retained Heap高的对象的引用链,判断是否合理。 > 示例:若某个`Context`对象的Retained Heap异常大,通过引用链发现其持有一个未关闭的数据库连接集合,即可定位泄漏点。 ### 相关问题 1. 如何在MAT工具中分析Retained Heap最高的对象? 2. 哪些常见代码模式会导致Retained Heap过高? 3. Shallow Heap对象实际内存占用有何差异? 4. 如何通过断开引用链减少Retained Heap? [^1]: [引用1] [^2]: [引用2] [^3]: [引用3] [^4]: [引用4] </think> ### Shallow HeapRetained Heap 详解 #### 1. **核心定义** - **Shallow Heap** 对象**自身占用的内存大小**,不包括其引用的对象[^2][^4]。 - 非数组对象:对象头 + 成员变量大小总 - 数组对象:所有元素大小总 *公式*: $$S(O) = \text{Header} + \sum \text{Field Sizes}$$ - **Retained Heap** 对象被垃圾回收(GC)后**可释放的总内存量**,包含: 1. 对象自身(Shallow Heap) 2. **仅通过该对象引用**的其他对象链(排除被 GC Roots 直接/间接引用的对象)[^3][^4]。 *公式*: $$R(O) = S(O) + \sum S(X) \quad (X \in \text{Uniquely Reachable Objects})$$ #### 2. **关键区别** | 特性 | Shallow Heap | Retained Heap | |---------------------|-------------------------------|-----------------------------------| | **计算范围** | 仅对象自身 | 自身 + 独占引用的对象链 | | **GC 意义** | 回收单对象释放的内存 | 回收对象及其独占对象链释放的总内存 | | **内存泄漏分析价值** | 低(不反映依赖关系) | **高**(定位内存黑洞) | | **依赖关系** | 独立于引用结构 | 依赖对象引用拓扑 | #### 3. **图解说明(基于引用[2][4])** ```mermaid graph TD GC_Roots[GC Roots] --> A GC_Roots --> B B --> C C --> D GC_Roots --> D %% D 被 GC Roots 直接引用 ``` - **A 的 Retained Heap**:仅 $S(A)$(无引用对象) - **B 的 Retained Heap**:$S(B) + S(C)$ ($D$ 被 GC Roots 直接引用,不计入 $B$ 的 Retained Heap[^4]) - **若 GC Roots 不引用 D**: $B$ 的 Retained Heap = $S(B) + S(C) + S(D)$ #### 4. **应用场景** 1. **内存泄漏分析** - Retained Heap 用于定位"内存黑洞"(如 MAT 的 Dominator Tree 视图按 Retained Heap 排序[^1])。 - *示例*:Activity 未销毁导致 Retained Heap 持续增长。 2. **性能优化** - Shallow Heap 优化:减少大数组或冗余字段。 - Retained Heap 优化:断开无效引用链(如静态集合持有无用对象)。 3. **GC 效率评估** -Retained Heap 对象会延长 GC 停顿时间(需回收更多关联对象)。 #### 5. **工具实践(MAT/JProfiler)** - **Histogram 视图**:默认显示 Shallow Heap,可切换为 Retained Heap 列。 - **Dominator Tree**:按 Retained Heap 排序,标识关键内存持有者。 - **Path to GC Roots**:分析高 Retained Heap 对象的引用链根源。 > ⚠️ **注意**:Retained Heap 计算需排除 GC Roots 关联对象(如线程栈/静态变量引用的对象)[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值