算法|JVM有几种垃圾回收(GC)算法,你知道吗?

算法|JVM有几种垃圾回收(GC)算法,你知道吗?


作为一名JAVA程序员 , 一般面试的时候最常准备的面试题就是JVM垃圾回收(GC)机制了 。 一般人都会知道 , 在开发过程中 , 会创建很多对象 , 这些对象都会存在于JVM内存模型的堆中 , 这样下去 , 堆空间很快就会被耗尽 , 所以JVM提供了垃圾回收机制 , 用于将一些没用的对象清理掉 。
那么 , JVM是怎么判断哪些对象是垃圾 , 又是怎么回收的呢?这就需要了解今天我们要讨论的主题 , JVM的垃圾回收算法了 。
那么 , 垃圾回收有几种算法呢?通常来说 , JVM的垃圾回收算法一共有以下几种 。
一、串行GC(Serial GC)
串行GC是很简单的一种GC算法 , 它对年轻代使用 mark-copy(标记-复制) 算法 , 对老年代使用 mark-sweep-compact(标记-清除-整理)算法 。 而这两者都是单线程的垃圾收集器 , 并不能进行并行处理 。 因此 , 两者都会触发全线暂停(stop the world STM) , 停止所有的应用线程 。 因此这种GC算法不能充分利用多核CPU 。 不管有多少CPU内核 JVM 在垃圾收集时都只能使用单个核心 。
所以这种算法只适合于几面MB堆内存的JVM , 在单核CPU的情况下使用 。 它的JVM参数配置如下:
java -XX:+UseSerialGC
二、并行GC(Parallel GC)
相对于串行GC而言 , 顾名思义 , 并行GC可以通过并行执行来减少GC时间 , 其使用的算法和串行GC一样 , 也是对年轻代使用 mark-copy(标记-复制) 算法 , 对老年代使用 mark-sweep-compact(标记-清除-整理)算法 , 但是在标记和复制/整理阶段都会使用多个线程 。 因此适用于多核处理器 。 它的JVM参数配置可以使用-XX:+UseParallelGC 或-XX:+UseParallelOldGC
三、CMS GC (Concurrent Mark Sweep GC)
CMS算法与以上两种算法一样 , 也是面向分代的垃圾回收算法 , 主要面向老年代进行垃圾收集 , 其尝试通过使用单独的垃圾收集器线程在执行应用程序线程的同时执行并跟踪可访问对象 , 来减少由于主要收集而导致的暂停时间 。 在并发标记阶段 , CMS GC会把发生变化的对象所在的Card标识为Dirty , 这样后续就只需要扫描这些Dirty Card的对象 , 从而避免扫描整个老年代 。 这样 , 就达到了减少应用停顿时间的目的 。
CMS的问题在于堆内存碎片化问题无法得到解决 , 因此 , JVM有可能会触发Full GC来进行碎片整理 。
CMS GC的参数配置如下:
-XX:+UseConcMarkSweepGC
四、G1 GC
为克服CMS GC的缺点 , 在JDK1.7中引入了G1 GC , G1 GC在并发回收的同时 , 会对对象进行适合的移动 , 有效的复制对象 , 从而减少空间碎片的产生 。 在G1 GC中 , 如果清除步骤发现所有的区别都是由可回收垃圾组成的 , 则会立即回收这些空间 , 并且将这些空间插入到一个LinkedList实现的空闲队列里 , 这一特点也是G1 GC和其它GC的最大差别 。
但是在一些特殊情况下 , G1 GC可能会增加Java堆的尺寸 。 例如在Full GC中 , 基于堆尺寸的计算结果会调整堆的空间 。 或者在一个对象分配失败的时候 , G1会尝试增加堆尺寸来满足对象分配等 。
G1 GC涉及到的JVM参数如下 , 从JAVA 9开始 , G1 GC是默认的GC算法 , 此前并行GC是默认算法:
-XX:UseG1GC
-XX:G1HeapRegionSize
-XX:G1MaxNewSizePercent
-XX:G1NewSizePercent
-XX:MaxGCPauseMillis
-XX:ConcGCThreads
-XX:ParallelGCThreads
-XX:G1MixedGCLiveThresholdPercent
-XX:InitiatingHeapOccupancyPercent
-XX:G1HeapWastePercent
-XX:G1OldCSetRegionThresholdPercent