一、垃圾回收算法
本文开始之前,先列一下垃圾回收所涉及到的算法,方便理解:
标记-复制
它将可用内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块用完之后,就将还存活的对象复制到另外一块上面,然后在把已使用过的内存空间一次理掉。它的优点是实现简单,效率高,不会存在内存碎片。缺点就是需要2倍的内存来管理。标记-清除
标记清除算法分为“标记”和“清除”两个阶段:首先标记出需要回收的对象,标记完成之后统一清除对象。它的优点是效率高,缺点是容易产生内存碎片。标记-整理
标记操作和“标记-清理”算法一致,后续操作不只是直接清理对象,而是在清理无用对象完成后让所有 存活的对象都向一端移动,并更新引用其对象的指针。因为要移动对象,所以它的效率要比“标记-清理”效率低,但是不会产生内存碎片。分代收集算法
这种算法并没有特别的思想,只是将内存划分为不同的块(新生代,老年代),然后根据不同年龄代的内存特点选择合适的垃圾回收算法。
二、垃圾收集器
下图来自于<<深入理解java虚拟机>>,如果垃圾收集器之间有连线,说明可以组合使用。
三、垃圾收集器对比
垃圾收集器名称 | 使用算法 | 适用年龄代 | 特性 |
---|---|---|---|
Serial | 复制算法 | 新生代 | 单线程,Client模式下的默认新生代收集器 |
ParNew | 复制算法 | 新生代 | Serial收集器的多线程版本,Server模式下的首选新生代收集器 |
Parallel Scavenge | 复制算法 | 新生代 | 多线程,吞吐率优先的收集器 |
Serial Old | 标记整理 | 老年代 | 单线程,主要在Client模式下使用 |
Parallel Old | 标记整理 | 老年代 | 多线程,主要配合Parallel Scavenge使用 |
CMS | 标记清除 | 老年代 | 多线程, 停顿时间短,响应速度快 |
G1 | - | - | 可预期的GC停顿周期,分代收集,内存碎片整理 |
收集器详细说明:
Serial(串行)收集器
在jdk1.3.1之前,java虚拟机仅仅能使用Serial收集器。 Serial收集器是一个单线程的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。
PS:开启Serial收集器的方式
-XX:+UseSerialGCParallel(并行)收集器
Parallel收集器也称吞吐量收集器,相比Serial收集器,Parallel最主要的优势在于使用多线程去完成垃圾清理工作,这样可以充分利用多核的特性,大幅降低gc时间。
PS:开启Parallel收集器的方式
-XX:+UseParallelGC -XX:+UseParallelOldGCCMS(并发)收集器
CMS收集器在Minor GC时会暂停所有的应用线程,并以多线程的方式进行垃圾回收。在Full GC时不再暂停应用线程,而是使用若干个后台线程定期的对老年代空间进行扫描,及时回收其中不再使用的对象。
PS:开启CMS收集器的方式
-XX:+UseParNewGC -XX:+UseConcMarkSweepGCG1(并发)收集器
G1收集器(或者垃圾优先收集器)的设计初衷是为了尽量缩短处理超大堆(大于4GB)时产生的停顿。相对于CMS的优势而言是内存碎片的产生率大大降低。
PS:开启G1收集器的方式
-XX:+UseG1GC
四、垃圾收集器参数总结
五、小结
本文主要复习了一下常用的垃圾回收算法和垃圾收集器,对一些主要的参数进行了说明。