GC 要解决三个主要的问题:
哪些内存需要回收?
什么时候回收?
如何回收?
哪些内存需要回收?
最简单的是引用计数(reference count), 缺陷是无法解决循环引用. 于是更快点的算法是可达性分析(reachable analysis).
什么时候回收?
至少要经历两次标记过程:
在进行可达性分析后, 发现没有与 GC roots 相连接的引用链时, 会被第一次标记并进行一次筛选 -- 是否有必要执行 finalize().
对象没有 finalize()方法或者被虚拟机执行过, 视为 "没必要执行"
有必要执行 finalize(), 被放置于 F-Queue 队列中, 并在稍后由(虚拟机自动建立的, 优先级低的)Finalizer 线程去 "执行"(触发相应方法, 但并不会等待它完成).
之后 GC 将对 F-Queue 中对象进行第二次小规模的标记.
如何回收?
Mark-Sweep(标记 - 清除):(缺陷: 会造成大量的内存碎片.)
Copy: 内存一分为二, 每次只使用其中的一半. 清理时, 将存活对象拷贝到未使用的另一半, 再将已用的这一半清理掉.(缺陷: 将内存缩小为原来的一半, 在存活对象较多时效率很低. 所以在新生代区域会使用这种算法, 一大块 Eden 和两块 Survivor 区域. 每次使用 Eden 和其中一块 Survivor 区域.)
Mark-Compact(标记 - 整理): 让所有存活的对象, 往一端移动, 适用于存货对象较多的区域, 如老生代.
分代收集: 综合了以上所有方法, 对不同的 generation 区域使用不同的算法.
来源: http://www.bubuko.com/infodetail-2648039.html