首先, Dalvik虚拟机比其他Java虚拟机中的垃圾收集要简单一些, 因为没有进行内存整理(no compacting). 也就是说堆内存中的对象在创建之后其地址永远都不会发生改变, 使得虚拟机其余部分的实现变得相对简单。
而GC会在 分配失败时触发, 包括以下情况:
- 触发
OutOfMemoryError
时, - 堆内存的大小到达某些软限制时,
- 显式地请求GC时。
每种情况都有相应的标准来标识是否是 partial GC(部分GC, 只回收 active heap), 是否是 concurrent GC (并发GC, 在应用线程运行时执行大部分的对象标记任务), 以及是否是 preserving GC (保留GC, 保留软引用)。
典型的GC是由于内存限制所引起的, 只清理活跃堆,并发型和保留型的GC. 另一种触发GC的原因是 OutOfMemoryException
, 是同步的,非保留式的(non-preserving)。
当前(Android 4.x) 使用的是 Mark-Sweep algorithm(标记清除)算法。
Mark-Sweep Algorithm(标记-清除算法)的处理过程
标记和清除算法是编程界第一种能够回收 循环数据结构 的算法。
使用标记-清除算法时, 未引用的对象不会立刻回收。相反,垃圾可以堆积, 直到耗尽所有可用内存。当内存不足时, 程序被暂停执行, 然后标记-清除算法清理所有的垃圾. 当所有未引用的对象被回收后, 再恢复程序的正常运行。
标记-清除算法被称为 ** tracing 垃圾收集器, 因为其追朔( traces out) 所有直接或间接被程序访问的对象。 程序可以直接访问的对象包括: 处理器栈上的局部变量引用的对象, 以及静态变量所引用的对象。 在GC的上下文中, 这些变量被称为 GC根(root)。 间接可访问是指由(直接/间接)对象所引用的对象。可访问对象也被称为 存活对象. 相反, 不再存活的对象就是垃圾。
标记-清除算法分为 两个阶段:
第一阶段,找到所有的可访问对象并标记, 称为 mark 阶段。
第二阶段, 垃圾收集算法扫描整个堆, 并回收所有未标记的对象, 称为sweep阶段。
(a) 显示了垃圾收集之前的情况。在此示例中,只有单个 root 变量。
(b) 显示了 mark 阶段结束时的结果。此时, 所有的存活对象都被标记了。
(c) 显示了 sweep 阶段完成后留下的对象。只有存活对象留在内存中, 所有对象的 marked 字段再次被设置为false。
当然,到 Android5.0 以后, ART GC 的优化改进了Dalvik 虚拟机的很多性能瓶颈; 详情请参考: Android 5.0 ART GC 对比 Android 4.x Dalvik GC
此文也比较好: Android GC 从dalvik到ART的改进分析
原文链接: https://medium.com/@nitinkumargove/how-garbage-collection-works-in-dalvik-vm-in-android-bf781ab48531
翻译人员: 铁锚 http://blog.csdn.net/renfufei
翻译时间: 2017年01月26日