理解 Java GC(三)

本文主要讲解下GC的5中类型:

  1. Serial GC (-XX:+UseSerialGC)
  2. Parallel GC (-XX:+UseParallelGC)
  3. Parallel Old GC(-XX:+UseParallelOldGC)
  4. CMS GC (-XX:+UseConcMarkSweepGC)
  5. G1 GC

Serial GC (-XX:+UseSerialGC)

在之前的文章里,我们已经讲解过GC在 young generation采用的GC算法了。GC在 old generation采用的算法是”mark-sweep-compact”。

1、首先标记在“ old generation”存活的对象。(mark)
2、紧接着,从堆的起始位置开始检查,没有用的对象被清理掉,只剩下在1、中标记的存活的对象。(sweep)
3、最后,把所有存活的对象都连续地丢到堆的一端。这时,堆(更准确点是“old generation”)被分成两部分:一部分有对象,另一部分是空闲空间。(compact)

在内存不大,CPU核数不多的情况下采用此类型的GC。

Parallel GC (-XX:+UseParallelGC)

从下面的图中,我们可以很清楚的 区分serial GC和 parallel GC。即serial GC仅用一个线程去执行,而parallel GC用多个线程执行,因此,速度也快了起来。
当内存足够,CPU核数也OK的情况下,这种类型的GC是非常有用的。它也叫作“throughput GC.” (就是可以提高系统的吞吐量)

Parallel Old GC(-XX:+UseParallelOldGC)

Parallel Old GC从JDK5之后出现。通过和上面的parallel GC比较,我们会发现它们的区别仅仅是在处理“ old generation”上。

具体来说,它分为3步:mark-summary-compaction在summary这一步中,从上一步(mark)标记的区域中互不影响地识别出那些存活的对象,这个和“mark-sweep-compac”中“sweep”是不同的,它包含稍微复杂的几步。

CMS GC (-XX:+UseConcMarkSweepGC)

理解 Java GC(三)_第1张图片
正如上图所示,CMS GC(Concurrent Mark-Sweep GC)比之前提到的任何类型的GC更加复杂。

最初的初始化标记是很简单的一步。离类加载器最近的存活的对象会被搜索到。因此,暂停时间超短。
在并行标记这步中,在上步中已经确认存活的对象所引用的对象将会被跟踪和检查。这两步的区别是上一步“stop-the-world”,而这一步是有用户线程在并行执行。在并行标记步骤中,一直被引用的对象刚刚加入或者停止的都将被检查。
最后,在并行清理步骤中,GC开始回收垃圾。GC线程同样是和其他用户线程并行执行。既然CMS GC以这种方式执行,那它暂停时间短暂也将不足为奇了。所以, CMS GC也称为 “low latency GC”(短等待GC),常被应用在响应时间要求极高的环境下。

说完了CMS GC的优点,接下来我们聊聊它的弊端:

  • 和其他类型GC相比,它占用更多内存和CPU时间;
  • 默认是不提供压缩步骤的。

如果你还有疑问,可返回去比较之前提到的GC类型。压缩工作可以减少内存碎片,但同时耗时也长,特别是在“stop-the-world“。你可以经常检查下压缩工作的耗时。

G1 GC

要理解G1 GC(Garbage First GC),你要抛弃目前你所了解到的关于 young generation 和 the old generation的知识。
理解 Java GC(三)_第2张图片
正如上图所示 ,一个对象被分配到一个网格中,接着执行GC。一旦一片空间用完,就会开始使用另外一片空间,然后GC开始清理。之前提到的数据在young generation 经过3个空间的转移最后会被丢到the old generation,这种清理方式在G1 GC是看不到的。
G1 GC是用来取代CMS GC的,从长远来看,CMS GC会带来一堆问题。

G1 GC的性能是为人称道的。它比目前我们提到的任何类型的GC更加高速。但在JDK6中,被认为是早期的一种方式,而且只能用来测试。不过在JDK7中,已经被采用了。我自己觉得,在NHN在实际应用中采用JDK7之前,我们是需要大量的测试的。所以你可能要等一段时间。当然,我听说JVM在JDK6中采用了G1 崩溃了几次。所以等它的稳定版吧。(笔者加注:目前JDK 8都已经出来了,作者这篇文章写于12年,不要在意哈)

在后续讲解中,我们谈谈GC调优。先思考下这个问题:

如果应用程序创建的所有对象的大小和类型都确定,可以识别,那公司里采用所有的GC选项都可以一样了。但一个对象的大小和生命周期是依赖于应用的,而且类型也有可能发生改变。换言之,一个应用采用GC选项中的”A”方案,并不意味着可以直接复制到另一个应用上。所以,通过持续的监控和调整,我们才能找到最合适自己应用的方案。

好了,下一篇文章我们开始讲解如何监控GC并调优。

你可能感兴趣的:(java,jvm,GC)