Android垃圾回收算法详解
这是Android面试中的重要考点,涉及JVM内存管理和性能优化。
一、常见垃圾回收算法
1. 标记-清除算法 (Mark-Sweep)
工作原理:
第一步:标记 - 标记出所有需要回收的对象
第二步:清除 - 统一回收所有被标记的对象
优点:
实现简单
不需要移动对象
缺点:
- ❌ 产生内存碎片 - 大量不连续的内存碎片,可能导致大对象无法分配
- ❌ 效率不高 - 标记和清除两个过程效率都不高
- ❌ 需要暂停应用(Stop The World)
示意图:
回收前: [对象A][空闲][对象B][对象C][空闲][对象D]↓ 标记B和D为垃圾
回收后: [对象A][空闲][空闲][对象C][空闲][空闲]↑ 产生大量碎片
2. 标记-整理算法 (Mark-Compact)
工作原理:
第一步:标记 - 标记出所有需要回收的对象
第二步:整理 - 让所有存活对象向一端移动
第三步:清理 - 清理掉边界以外的内存
优点:
✅ 不产生内存碎片
✅ 内存利用率高
缺点:
- ❌ 需要移动对象,效率较低
- ❌ 需要更新所有引用指针
- ❌ 暂停时间较长
示意图:
回收前: [对象A][空闲][对象B][对象C][空闲][对象D]↓ 标记并整理
回收后: [对象A][对象C][空闲空闲空闲空闲空闲]↑ 连续的空闲空间
3. 复制算法 (Copying)
工作原理:
将内存分为两块相等的区域(From和To)
1. 只使用其中一块(From区)
2. 垃圾回收时,将From区存活对象复制到To区
3. 清空整个From区
4. 交换From和To的角色
优点:
- ✅ 效率高 - 只需遍历存活对象
- ✅ 不产生碎片 - 复制到To区时按顺序排列
- ✅ 分配内存简单 - 只需移动指针
缺点:
- ❌ 浪费50%内存空间
- ❌ 如果存活对象多,复制开销大
- ❌ 需要额外空间保证
示意图:
From区: [对象A][对象B][垃圾][对象C][垃圾]↓ 复制存活对象
To区: [对象A][对象B][对象C][空闲空闲]↓ 交换角色
新From: [对象A][对象B][对象C][空闲空闲]
新To: [空闲空闲空闲空闲空闲空闲空闲]
4. 分代收集算法 (Generational Collection)
核心思想:
根据对象存活周期将内存划分为几块,不同代采用不同的回收算法。
理论依据:
- 弱分代假说:大部分对象都是朝生夕死
- 强分代假说:熬过越多次GC的对象越难消亡
分代结构:
Java堆内存
├── 新生代 (Young Generation) - 占1/3堆空间
│ ├── Eden区 (8/10)
│ ├── Survivor From区 (1/10)
│ └── Survivor To区 (1/10)
└── 老年代 (Old Generation) - 占2/3堆空间
工作流程:
1. 新对象分配到Eden区
2. Eden区满时触发Minor GC- 存活对象复制到Survivor To区- From和To交换
3. 多次Minor GC后仍存活的对象晋升到老年代
4. 老年代满时触发Major GC/Full GC
各代使用的算法:
- 新生代 → 复制算法(对象存活率低,复制少量对象效率高)
- 老年代 → 标记-清除 或 标记-整理(对象存活率高,不适合复制)
二、Android采用的垃圾回收算法
Android的GC演进历史

当前主流:Concurrent Copying GC
核心特点:
✅ 并发复制 - 应用运行时并发进行GC
✅ 分代收集 - 区分年轻代和老年代
✅ 压缩整理 - 减少内存碎片
✅ 暂停时间短 - 典型暂停 < 10ms
工作原理:
年轻代收集(频繁):
1. 使用半空间复制算法
2. Eden满时触发
3. 存活对象复制到Survivor或晋升到老年代老年代收集(不频繁):
1. 并发标记阶段(应用运行中)
2. 短暂暂停阶段(标记根对象)
3. 并发复制阶段(移动对象,应用继续运行)
4. 清理阶段
三、Android为什么选择这种算法?
1. 移动设备的特殊需求
❌ 内存有限 → 需要高效内存利用
❌ 性能敏感 → 不能长时间暂停(避免卡顿)
❌ 电池约束 → GC不能过于频繁消耗电量
✅ 交互优先 → 必须保证流畅度(60fps)
2. 应用场景特点
Android应用特性:
- 大量短生命周期对象(View、Bitmap临时对象)
- 频繁的对象创建和销毁
- 用户交互对延迟非常敏感
- 分代收集的优势:
// Android典型场景
void onDraw(Canvas canvas) {Paint paint = new Paint(); // 短生命周期对象canvas.drawText("Hello", paint); // 用完即丢
}
// ↓
// 这些对象在Minor GC中快速回收,不影响UI流畅度
3. 技术对比

四、面试高频问题
Q1: Android的GC会Stop The World吗?
A: 现代Android(5.0+)的GC主要是并发执行的,只在少数阶段(如标记根对象)有短暂暂停(通常<10ms),大幅减少了STW时间。
Q2: 为什么分代收集适合Android?
A: 因为Android应用中90%以上的对象都是短生命周期(如临时View、临时Bitmap),分代收集能高效回收这些对象,同时不影响长期存活的对象。
Q3: 如何减少GC对性能的影响?
A:减少临时对象创建(使用对象池、StringBuilder等)
避免内存泄漏(使用LeakCanary检测)
及时释放大对象(Bitmap.recycle())
使用内存分析工具(Android Profiler)
Q4: Dalvik和ART的GC有什么区别?
A:Dalvik: 使用标记-清除,STW时间长,JIT编译
ART: 使用并发复制GC,暂停时间短,AOT预编译
Q5: 什么时候会触发Full GC?
A:老年代空间不足
方法区空间不足
显式调用System.gc()(不推荐)
晋升担保失败
理解GC机制对写出高性能Android应用至关重要!
