垃圾回收器
java虚拟机规范对垃圾收集器应该如何实现没有任何规定,因为没有所谓最好的垃圾收集器出现,更不会有万金油垃圾收集器,只能是根据具体的应用场景选择合适的垃圾收集器。
连线说明,他们经常是这么搭配使用的。其中常用的是parnew+cms的搭配。同时因为G1垃圾回收器的特殊性,所以他是兼顾新生代和老年代一起使用。
Serial和Serial Old垃圾回收器
分别用来回收新生代和老年代的垃圾对象
Serial
新生代采用复制算法,老年代采用标记-整理算法。
工作原理就是单线程运行,垃圾回收的时候会停止我们自己写的系统的其他工作线程,让我们系统直接卡死不动,然后让他们垃圾回收,这个现在一般写后台Java系统几乎不用。
但是Serial收集器有没有优于其他垃圾收集器的地方呢?当然有,它简单而高效(与其他收集器的单线程相比)。Serial收集器由于没有线程交互的开销,自然可以获得很高的单线程收集效率。Serial收集器
对于运行在Client模式下的虚拟机来说是个不错的选择。
Serial Old收集器
Serial收集器的老年代版本,它同样是一个单线程收集器。它主要有两大用途:一种用途是在JDK1.5以及以前的版本中与Parallel Scavenge收集器搭配使用,另一种用途是作为CMS收集器的后备方案。
什么叫CMS垃圾回收器的后备方案?
我们在使用CMS垃圾回收器时,CMS垃圾回收的触发时机,其中有一个就是当老年代内存占用达到一定比例了,就自动执行GC。
“-XX:CMSInitiatingOccupancyFaction”参数可以用来设置老年代占用多少比例的时候触发CMS垃圾回收,JDK 1.6里面默认的值是92%。
也就是说,老年代占用了92%空间了,就自动进行CMS垃圾回收,预留8%的空间给并发回收期间,系统程序把一些新对象放入老年代中(因为我们知道在cms垃圾回收的第二第三阶段是不进行STW的,此时项目还在运行那么可能对象还是会进入老年代,所以这百分之8是给他们准备的)
那么如果CMS垃圾回收期间,系统程序要放入老年代的对象大于了可用内存空间,此时会如何?
这个时候,会发生Concurrent Mode Failure,就是说并发垃圾回收失败了,我一边回收,你一边把对象放入老年代,内存都不够了。
此时就会自动用“Serial Old”垃圾回收器替代CMS,就是直接强行把系统程序“Stop the World”,重新进行长时间的GC Roots追踪,标记出来全部垃圾对象,不允许新的对象产生。
然后一次性把垃圾对象都回收掉,完事儿了再恢复系统线程。
所以在生产实践中,这个自动触发CMS垃圾回收的比例需要合理优化一下,避免“Concurrent Mode Failure”问题