概述

最近在剖析一个内存占用问题,就经过 AS 的 Memory Profile (卡是真的卡)去查看了一下内存状况,看到了两个 Size,官方解说:

  • Shallow Size: Total amount of Java memory used by this object type (in bytes); Size of this instance in Java memory.
  • Retained Size: Total size of memory being retained due to all instances of this class (in bytes); Size of memory that this instance dominates (as per the dominator tree).

类似下图(事务代码的剖析不方便贴出,随手写的 Demo 代码):

Android优化篇|Shallow Size & Retained Size

这篇文章咱们再温习一下 Shallow SizeRetained Size 这两个概念,在此之前需要对 Java GC 机制有必定的了解,曾经有记载过这块的内容,有爱好可以参考看看 Java 垃圾收回机制。需要注意一下 GC Root,它们不会被 GC 收回,典型的 GC Root 就是静态变量,被 GC Root 直接 or 直接引证的对象也不会被收回。

Shallow Size

Shallow Size是指实例本身占用的内存,不包含它引证的其他实例。即:

Shallow Size = 类界说 + 特点占用空间 + 位数对齐

在我的 64 位机器上测验如下:

  • 类界说:声明一个类本身所需的空间,固定为 8 个字节。类界说空间不会重复核算,即便类承继了其他类,也只算 8 个字节。界说了一个没有任何特点的类,查看其 Shallow Size 巨细为 8 个字节。
  • 特点占用空间:所有特点所占空间之和,包含本身的和父类的所有特点。特点分为根本类型和引证,如 int 类型占 4 个字节,long 类型占 8 个字节,引证固定 (String, Reference) 占 4 个字节。
  • 位数对齐:使总空间为 8 的倍数。比方某个类以上两项共 21 字节,那么为了对齐,会取最接近 8 的倍数的值,即它的 Shallow Size 是 24 个字节。与体系有关,有的不会对齐。

上面给出的截图,类结构如下,可以看出它就没有 位数对齐 这一项:

// Shallow Size = 28 = 8 + 4 + 8 + 4 + 4
// Retained Size = 36 = 28 + 8
data class Resource(
    val int: Int,
    val long: Long,
    val string: String,
    val reference: Res
)
// Shallow Size = 8
class Res()

Retained Size

Retained Size 是指某个实例被收回时,可以一起被收回的实例的 Shallow Size 之和。

因而在进行内存剖析时,咱们需要要点关注 Retained Size 较大的实例;另外也可以经过 Retained Size 判断出某个实例内部使用的实例是否被其他实例引证,比方说假如某个实例的 Retained Size 比较小,Shallow Size 比较大,说明它内部使用的某个实例还在其他地方被引证了(比方说对 Bitmap 实例而言,假如它的 Retained Size 很小,可以说明它内部的 byte 数组被另外的 Bitmap 实例复用了)。

举个栗子

现在有几个实例的引证关系如下图,假设每个实例的 Shallow Size 都为 X:

Android优化篇|Shallow Size & Retained Size

别离考虑收回这四个实例后,能开释的空间,即 Retained Size 巨细,咱们简单把某个实例 A 的 Retained Size 记作 R(A),Shallow Size 记作 S(A)。

  1. 移除 D 实例:D 没有引证任何实例,因而只会开释本身的 Shallow Size,即 R(D) = S(D) = X
  2. 移除 C 实例:移除 C 后,因为它引证了 D,且 D 没有被其他实例引证,因而 D 也会被一起收回,即 R(C) = S(C) + S(D) = 2X
  3. 移除 B 实例:移除 B 后,因为 B 和 A 实例都引证了 C 实例,所以移除 B 并不会让 C 实例被 GC 收回。即 R(B) = S(B) = X
  4. 移除 A 实例:B、C、D 实例被一起收回,即 R(A) = S(A) + S(B) + S(C) + S(D) = 4X

写在最终

在写这篇文章的时分翻了一些网上的博客,许多都是抄来抄去,或许说法各一,上面的数据经过了我自己的测验,发现 Shallow Size 具体巨细的核算这儿跟网上有些说法不太共同,有了解这块的同学可以谈论区沟通。

文中内容如有错误欢迎指出,共同进步!更新不易,觉得不错的留个再走哈~


Android视图体系:Android 视图体系相关的底层原理解析,看完定有收获。

Kotlin专栏:Kotlin 学习相关的博客,包含协程, Flow 等。

Android架构学习之路:架构不是一蹴而就的,期望咱们有一天的时分,可以从自己写的代码中找到架构的成就感,而不是干几票就跑路。作业太忙,更新比较慢,我们有爱好的话可以一起学习。

Android实战系列:记载实践开发中遇到和处理的一些问题。

Android优化系列:记载Android优化相关的文章,继续更新。