分代收集:
- 根据各个年代的特点选取不同的垃圾回收算法
- 新生代使用复制算法
- 老年代使用标记-整理或者标记-清除算法
- jps -v 显示当前使用的垃圾回收器
在新生代中,每次垃圾收集是都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集,而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理” 或者 “标记-整理” 算法来进行回收
请记住下图的垃圾收集器和之间的连线关系。
并行:垃圾回收的多线程的同时进行
并发:垃圾回收的多线程和应用的多线程同时进行
注:吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾回收时间)
垃圾收集时间 = 垃圾回收频率 * 单次垃圾回收时间
各种垃圾回收器
Serial/Serial Old
最古老的,单线程,独占式,成熟,适合单 CPU 服务器
-XX:+UseSerialGC 新生代和老年代都用串行收集器
-XX:+UseParNewGC 新生代使用 ParNew ,老年代使用 serial Old
-XX:+UseParallelGC 新生代使用 ParallerGC ,老年代使用 Serial Old
ParNew
和 Serial 基本没区别,唯一的区别:多线程,CPU的,停顿时间比 Serial 少
+XX:UseParNewGC 新生代使用 ParNew ,老年代使用 Serial Old
除了性能原因外,主要因为除了 Serial 收集器,只有它能与 CMS收集器配合工作
Parallel Scavenge(ParallerGC) / Parallel Old
关注吞吐量的垃圾回收器,搞吞吐量则可以高效率的利用 CPU 时间,尽快完成程序的运行任务,主要适合在后台运算而不需要太多交互的任务。所谓吞吐量就是 CPU 用于运行用户代码的时间与CPU总消耗的时间比值,即
吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)
虚拟机总共运行了 100 分钟 ,其中垃圾收集话掉 1 分钟 ,那么吞吐效率就是 99%
Concurrent Mark Sweep (CMS)
收集器是一种以获取回收停顿时间为目标的收集器,目前很大一部分的 Java 应用集中在互联网或者 B/S 系统的服务器上,这类应用尤其种事服务器响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类需求
-XX:+UseConcMarkSweepGC , 一般新生代使用 ParNew,老年代的用CMS
从名字(包含“Mark Sweep”)上就可以看出,CMS收集器是基于 “标记清除” 算法实现的,他的运作过程相对于前面几种收集器来说更复杂一些。
垃圾回收过程
整个过程分为 4 个步骤,包括:
1、初始标记:仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快,需要停顿
2、并发标记:从 GC Roots开始对对重对象进行可达性分析,找到存活对象没他事整个回收过程中最耗时最 长的,不需要停顿
3、重新标记:未来修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录, 需要停顿。这个阶段的停顿时间会比初始标记阶段稍长一些,但远比并发标记的时间短
4、并发清楚:不需要停顿
优点:由于整个过程中耗时最长的并发标记和并发清除过程收集器都可以与用户线程一起工作,所以,从总体上来说,CMS收集 器回收过程是与用户线程一起并发执行的
缺点:CPU 资源敏感:因为并发阶段多线程各占据CPU 资源,如果 CPU资源不足,效率会明显降低
浮动垃圾:由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾 出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就 称为“浮动垃圾”。由于浮动垃圾的存在,因此需要预留出一部分内存,意味着 CMS 收集不能像其它收集器那 样等待老年代快满的时候再回收。在1.6的版本中老年代空间使用率阈值(92%)。如果预留的内存不够存放浮 动垃圾,就会出现 Concurrent Mode Failure,这时虚拟机将临时启用 Serial Old 来替代 CMS。
会产生空间碎片:标记 - 清楚算法会导致产生比连续的空间碎片
G1垃圾回收器
G1 中的重要参数:
-XX:+UseG1GC 使用 G1垃圾回收器
内部布局改变
G1 把堆划分成多个大小相等的独立区域(Region),新生代和老年代不再物理隔离。
算法:标记—整理 (old,humongous) 和复制回收算法(survivor)。