Android GC 简史

本文探讨了Android GC从Dalvik到ART的发展历程,包括内存分配和回收的改进,如分代管理、并发复制GC等。介绍了Android不同版本中GC的特性,如Dalvik的内存碎片问题和ART如何解决这个问题。同时,文章还提及了Android对Bitmap内存处理的演进,以及大量内存使用和内存抖动对应用性能的影响。最后,指出随着ART的进步,开发者对GC的直接关注已减少,更多关注业务和应用性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

猫猫能有什么错呢?就这样被GC了...

Android 开发者对于 GC 既熟悉又陌生,听说过很多虎狼之词,对一些问题又不置可否;今天聊聊 Android 里的 GC,如果你对于下面的问题有兴趣又没答案,那你应该会有些收获:

  1. JVM、Dalvik、ART, 它们之间是什么关系?
  2. 所有版本的 Android 都是分代管理堆内存吗?
  3. 垃圾对象到底是怎么被回收的?
  4. 「内存抖动」你怕不怕?
  5. 作为一个应用层开发者,我真的需要关心 Android GC 吗?

前言:概念辨析

为了避免一些朋友不是很清楚概念,在正文开始之前,先简单辨析一下:

GC
GC,是指垃圾回收 (Garbage Collection),是一些语言管理内存的方式,如 Java 语言等;程序员不需要主动管理内存,程序运行时环境(虚拟机)会做垃圾回收的工作,就是在合适的时机 自动释放不再需要的内存。

与 GC 对应的是 native 语言,它需要程序员主动释放申请内存,忘记释放或者释放时机不合适都会产生问题。

GC Root
在 native 语言中,内存的申请和释放需要程序员来操作,做到正确地申请和释放内存就是程序员要考虑的问题。

在类似 Java 这种使用了 GC 的语言中,程序员不关心内存的释放。正确地释放内存就是 GC 的责任,GC 的原则是保证正确性的前提下,尽可能提升性能。 于是就使用了 GC Root 的机制,逻辑上就是:GC 认为 GC Root 以及它引用的对象是程序后面的可能会用到的,所以不会释放;没有被 GC Root 直接或间接引用的对象,后面一定不会被用到,可以被释放掉。

在 Java 中常被用于GC Root的类型如下:

  • (函数未出栈时的)局部变量
  • 静态变量
  • 存活状态的线程
  • Native 方法中 JNI 引用的对象

另外,Java 中内存泄漏的本质,就是对象 (不当地) 被GC Root 引用导致无法释放。

之所以会在这里提到 GC Root, 因为后面的流程中上来就先找 GC Root 集合,看完这个你就知道那是在干嘛了。

JVM / Dalvik / ART
JVM 是 Java 语言提出的虚拟机标准,基于这个标准各个厂商会有自己的实现。比如 Oracle 的 HotSpot,以及 Android 中的 DVM (Dalvik Virtual Machine) 和 ART (Android Runtime) 两个实现。其中,

  • Dalvik 是 Android 4.4 (Kitkat) 以及之前的版本的虚拟机;
  • ART 在 Android 4.4 (Kitkat) 引入,并在Android 5.0 (Lollipop) 开始取代Dalvik.

分代管理
分代管理是很多 JVM 虚拟机对于堆 (heap) 内存的管理机制,最为人熟知的是新生代 (Young Generation)、老年代 (Old Generation) 和永久代 (Permanent Generation) 这一组名词,这也是很多人讲 GC 时的默认组合。事实上,这一组名词是 Oracle 的 HotSpot 中对于 JDK 1.7及之前的实现方式。至于其他的 JVM 实现,可以选择是否采用分代管理的机制。

比如 Dalvik 就没有采用分代管理的机制,ART 在 Android 8 (Oero) 和 9 (Pie) 版本未使用分代管理、其他的版本又采用了该机制。

在分代管理的虚拟机中,新生代和老年代正如它们的名字一样,分别存储了新创建的对象和存活了很久的对象;新的对象会在新生代中创建,经过一定次数的 GC 后依然存活的对象,会被复制到老年代中(有些虚拟机新生代分为更多的区域,以达到的最佳的戏能表现)。


前言结束,现在进入今天最重要的部分了

Android GC 的演进

史前时代的 Dalvik

Dalvik 虚拟机随着 Android 一起诞生,一直到 Android 4.4。

HTC G1 是第一款 Android 设备,内存为192MB,应用程序可用的堆内存仅为30MB左右,Dalvik 就是在这样的环境下诞生的。它的设计原则中,节省空间 (尽量让程序跑起来) 是第一优先级。

HTC G1

内存分配

分配内存时,Dalvik 使用的算法是 dlmalloc (以 java.util.concurrent 作者 Doug Lea 命名的算法),使用了单独的进程来分配内存,内存的分配效率较低。

  • 在整个堆中寻找适合分配的内存
    在整个堆中寻找适合分配的内存

  • 找到了适合分配的内存
    找到了适合分配的内存

  • 内存分配成功
    内存分配成功

  • 上面的图中给出了顺利分配内存的流程,如果当前堆中没有合适分配的内存,就会触发一个 GC_FOR_ALLOC 进入GC流程。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值