Java GC 算法

JVM 提供了4种GC算法。

串行GC

4种GC种最简单的算法。在单CPU机器或者32位的windows上,JVM运行在client模式下。在这种模式下,缺省垃圾回收的算法就是串行GC.

字如其名,串行GC使用单线程来处理垃圾回收。当进行垃圾回收时,不管是minor GC,还是full gc,所有业务线程都会被stop。在full gc时,会全面压缩old区内存。

Throughput GC

针对多核平台,或者64bit JVM, JVM一般运行在server模式。在这种模式下,缺省垃圾回收算法是吞吐量优先GC.   

Throughput GC GC使用多线程对young区进行内存垃圾回收,这使得minor GC执行的速度比串行GC要快。配置XX:+UseParalleGC开启yong区的throuput GC。

当然Throughput GC GC也可以使用多线程对old 区进行垃圾回收。在JDK7之前,需要配置-XX;UseParallelOldGC参数开启old区的吞吐量优先GC算法。在JDK7u7之后,该特性默认开启,所以无需配置此参数。

在使用此算法进行minor GC或者full GC时,所有应用线程也会被stop。在进行full GC时,old区会被全面压缩。

CMS GC

不管是串行GC还是throuput GC,在进行GC时都会stop应用线程。为了减少GC造成的应用线程停顿时间过长,CMS GC应运而生。

在执行minor GC时,CMS也是使用多线程进行来及回收,也会stop 应用线程。但是和throughput GC不同的是,CMS使用了不一样的算法对young 区进行来及回收。CMS使用-XX:+UseParNewGC,throughput GC使用了-XX:+UseParalleGC。

在进行full GC时,CMS不会停止应用线程,而是使用后台线程周期性的扫描old 区并丢弃不再被使用的对象。通过这样的一个设计,CMS可以减少GC造成的应用线程停顿时间。为了达成这个目标,要付出的代价就是更多的CPU资源消耗。因为后台线程不会进行old区域的全全面压缩,也会造成old区域的内存碎片。如果没有足够的CPU资源或者old区域内存碎片化比较严重,CMS会退化为串行GC一样的行为:stop应用线程,然后以单线程的方式进行清理和压缩old区域内存。降低或者消除了old内存之后,CMS会回到预期的行为方式。

通过配置-XX:UseConMarkSweepGC(old 区域内存GC)、-XX:UseParNewGC(young 区域内存GC)方式开启CMS GC.

G1 GC

在超过4G的heap size时候,为了最小化的减少GC造成的停顿,就设计了G1 GC.  在大Heap配置下,heap在分代设计的基础上,进一步被切分成了若干区域。

和CMS 相同的一点是,G1 GC在对old区域进行垃圾回收时,也是使用后台线程进行处理,且不会stop应用线程。因为old区内存已经被切分成了若干区域,g1 gc会把一些仍然在用的对象copy到另外一个区域,减少了内存碎片化的程度,从而也减少了full GC的可能性。

和CMS一样,G1 GC也需要足够的cpu资源。配置-XX:UseG1 GC可以开启 G1 GC.

总结

1. 所有GC 在minor GC时,都会stop应用线程

2. throuput GC是一种吞吐量优先GC,会以多线程并行的方式进行yong和old区域垃圾回收,副作用会带来更长的停顿,使得应用响应时间边长

3. CMS 和G1线程都是并发式GC,old区域GC不会stop 应用线程,目标是减少停顿。保证应用线程的响应时间。CMS容易造成更多内存碎片,使得CMS 效果变差,而G1改善了内存碎片问题。

你可能感兴趣的:(Java GC 算法)