原文链接:http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/
GC老年代
老年代GC基本上是在空间慢的时候发生。执行过程与GC的类型有关,因此在你了解GC的种类之后更简单。
根据JDK7,有5中GC类型。
- Serial GC
- Parallel GC
- Parallel Old GC (Parallel Compacting GC)
- Concurrnt Mark & Sweep GC (or “CMS”)
- Garbage First(G1) GC
以上里面,serial GC一定不能用在服务器上。GC的类型在桌面计算机还只有一个CPU核的时候被创建。使用serial GC会极大的
减少性能。
下面我们来了解一下每种GC的类型。
Serial GC (-XX:+UseSerialGC)
新生代GC使用这种类型,我们在前面说过。老年代GC使用一种叫做“mark-sweep-compact”的算法。
- 算法的第一步是标记老年代中存活的对象。
- 然后,它从头开始检查堆,只留下存活的对象(清除)。
- 最后一步,它从头开始填满堆,并把堆分为两部分:一部分有对象,一部分没有对象(压缩)。
serial GC适合内存比较少和CPU核比较少的情况。
Parallel GC (-XX:+UseParallelGC)
图4 Serial GC与Parallel GC的区别
从图上,你可以轻易地看到Serial GC与Parallel GC的区别。serial GC只使用一条线程去执行GC,Parallel GC使用多条线程去处理GC,因此,它更快一点。这种GC在内存足够和CPU核很多的时候,会比较有用。因此叫做“throughput GC”。
Parallel Old GC(-XX:+UseParallelOldGC)
Parallel Old GC从JDK5更新的时候就开始得到支持。与Parallel GC相比,唯一的区别就是使用的老年代GC算法不一样。它有几步:标记-汇总-压缩。汇总这步与标记-清除-压缩算法中的清除步骤不一样的是,它将对象分配到GC预先处理!好的地方。这一步有一点复杂。
CMS GC (-XX:+UseConcMarkSweepGC)
图5 Serial GC与CMS GC
你可以从上图看到,并发标记-清除GC比前面提到的其他GC更复杂一点。最初的初始标记比较简单。离类加载器最近的存活对象被搜索到。因此暂停时间比较短。在并发标记步骤,存活对象被刚刚跟踪和确认的对象所引用。这一步的不同是它与其他线程在同一时间执行。在重标记步骤,在并发标记步骤新添加的对象或者停止的对象被检查。最后,在并发清除步骤,交给垃圾收集器处理。垃圾收集器在其他线程执行的时候启动。因为这种GC以这种方式执行,所以暂停时间非常短。CMS GC也叫做低时延GC,用在响应时间很严格的程序中。
这种GC有短的stop-the-world的时间的优点,也有下面的优点:
- 与其他GC类型相比,消耗更多的内存和CPU
- 默认是不支持压缩步骤的
你在使用这种GC前要仔细考虑。如果因为内存碎片过多,需要启动压缩任务时,stop-the-world时间就会比其他GC要长。你需要检查多频繁和多久执行一次压缩步骤。
G1 GC
最后,我们来学习一下garbage first(G1)GC。
图6 G1 GC的布局
如果你想了解G1 GC,忘记你所知道的所有关于新生代和老年代的东西。你可以从图中看出,一个对象被分配到一个格子中,然后GC被执行。然后,一旦一个区域满了,对象就会被分配到其他区域,然后GC就会执行。这里找不到数据从新生代移动到老年代的步骤。这种GC用来替代有很多问题并饱受争议的CMS GC。
G1 GC最大的优点是性能。它比我们前面讲的其他任何类型的GC都要快。但是在JDK6中,这叫做early access,并且只是用来测试。在JDK7中被正式加进来。我个人看来,在NHN能在实际服务中使用JDK7还需要很长时间(至少一年)。因此你必须等一等。另外,我经常听说JDK6在应用G1 GC之后,经常崩溃。在稳定之前请等一等。
我会在下面介绍GC优化,但是之前我要告诉你一件事。如果所有创建的对象的大小和类型在程序中是明确的,我们公司中使用的WAS的所有GC选项都会是一样的。但是WAS创建的所有对象的大小和类型都是依服务而定的,而且设备类型也千差万别。换句话说,仅仅因为特定的服务使用GC选项“A”,并不意味着不同的服务使用相同的选项就能获得最好的结构。有必要通过持续监控和优化找到WAS线程,每个设备的WAS实例和GC选项最合适的参数。这不是我个人的经验,这来自为JavaOne 2010创建Oracle JVM的工程师的讨论。
这个问题中,我们仅仅看了一下Java中的GC。我们在后面会了解更多关于怎么监控Java GC状态和优化GC。
我需要提醒一下,我参考了一本2011年11月出版的叫做“Java 性能”的书(亚马逊,可以通过Safari在线查到,如果有账号的话),和一本“Java HotSpot虚拟机内存管理”的Oracle官网提供的白皮书。
作者,Sangmin Lee,性能工程实验室高级工程师,NHN公司。