该算法分为“标记”和“清除”阶段:首先比较出所有需要回收的对象,在标记完成后统一回收掉所有被标 记的对象。它是最基础的收集算法,后续的算法都是对其不足进行改进得到。这种垃圾收集算法会带来 两个明显的问题:
为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一 块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 这样就使每次的内存回收都是对内存区间的一半进行回收。
根据老年代的特点提出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对 可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。
当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不 同将内存分为几块。一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合 适的垃圾收集算法。
比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制 成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分 配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。
串行垃圾回收器(Serial)
JVM第一个垃圾收集器,JDK 1.3.1之前都是有这个收集器。可以作用新生代和老年代。
算法:新生代使用复制算法,老年代使用标记-整理算法
特点:串行单线程、不支持并发、会导致"stop the world"
//配置如下使用
-XX:+UseSerialGC
并发垃圾回收器(parNew)
为了解决 serial拉圾收集器引起的停机问题,在serial基础上开发了多线程版本,但是parNew是针对client的版本。
算法:新生代采用复制算法、老年代采用标记-整理算法
特点:多线程、唯一能够与cms搭配使用的收集器
//强制指定使用ParNew
-XX:+UseParNewGC
//指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同
-XX:ParallerGCThreads
并行垃圾收集器(Parallel Scavenge)
Parallel Scavenge 收集器也是使用复制算法的多线程收集器,它看上去几乎和ParNew都一样。 那么它 有什么特别之处呢?Parallel Scavenge 收集器关注点是吞吐量(高效率的利用 CPU)。CMS 等垃圾收集器的关注点更多 的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值。 Parallel Scavenge 收集器提供了很多参数供用户找到最合适的停顿时间或最大吞 吐量,如果对于收集器运作不太了解的话,手工优化存在困难的话可以选择把内存管理优化交给虚拟机 去完成也是一个不错的选择。
算法:新生代复制算法,老年代标记-整理算法
特点:Parallel Scavenge 收集器关注点是吞吐量(高效率的利用 CPU),CMS 等垃圾收集器的关注点更多 的是用户线程的停顿时间(提高用户体验)
//注意:启动后不需要手工指定新生代的大小(-Xmn)、Eden和Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了
-XX:+UseAdaptiveSizePolicy
//使用Parallel收集器+老年代串行
-XX:+UseParallelGC
//启用并行压缩
-XX:+UseParallelOldGC。
并发垃圾回收器 CMS(Concurrent Mark Sweep)
cms主要是解决停顿时间的问题而开发的一种,低停顿、并发收集器,基于标记清除,可以作用于新生代和老年代。
初始标记: 暂停所有的其他线程,并记录下直接与 root 相连的对象,速度很快 并发标记: 同时开启 GC 和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域,所以GC 线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。 重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短 并发清除: 开启用户线程,同时 GC 线程开始对未标记的区域做清扫。
算法:标记-清除
特点:作用于新生代、老年代、低停顿、并发收集
缺点:无法处理浮动垃圾、对CPU资源非常敏感、会造成空间碎片化
//新生代使用并行收集器,老年代使用CMS+串行收集器
-XX:+UseConcMarkSweepGC
//设定CMS的线程数量
-XX:ParallelCMSThreads
G1垃圾回收器
初始标记(它标记了从GC Root开始直接可达的对象);
并发标记(从GC Roots开始对堆中对象进行可达性分析,找出存活对象);
最终标记(标记那些在并发标记阶段发生变化的对象,将被回收);
筛选回收(首先对各个Regin的回收价值和成本进行排序,根据用户所期待的GC停顿时间指定回收计划,回收一部分Region)。
//启用G1垃圾回收器
-XX:+UseG1GC
ZGC
ZGC 收集器是一款JDK 11 中新加入的具有实验性质的低延迟垃圾收集器,与Shenandoah 的目标相同,向往尽可能对吞吐量影响不大的前提下,实现在任意任意堆内存可以把垃圾收集停顿限制在十毫秒之内的低延迟。
Shenandoah
前言: Shenandoah 并不是Oracle 官方的收集器,所以 OracleJDK 甚至明确拒绝使用这个高效的垃圾收集器,商用的话可以使用OpenJDK。
该收集器与 G1 的不同有:
收集器 | 类型 | 区域 | 算法 | 特性 | 场景 |
---|---|---|---|---|---|
Seial | 串行 | 新生代 | 复制算法 | 响应速度优化 | 单CPU环境下的Client模式 |
Serial Old | 串行 | 老年代 | 标记-整理 | 响应速度优化 | 单CPU环境下的Client模式、CMS的后备预案 |
ParNew | 并行 | 新生代 | 复制算法 | 响应速度优先 | 多CPU环境时在Server模式下与CMS配合 |
Parallel Scavenge | 并行 | 新生代 | 复制算法 | 吞吐量优先 | 后台运算不需要太多交互任务 |
Parallel Scavenge old | 并行 | 老年代 | 标记整理 | 吞吐量优先 | 后台运算不需要太多交互任务 |
CMS | 并发 | 老年代 | 标记清除 | 响应速度优先 | 主要用于互联网站或B/S系统服务端上的Java应用 |
G1 | 并发 | 新生代/老年代 | 标记-整理+复制算法 | 响应速度优先 | 面向服务端应用,将来替换CMS |
查看jdk所用内存垃圾回收器
java -XX:+PrintCommandLineFlags -version
#oracle_jdk(java TM) 看不到使用了什么GC,但是可以从官网文档中看到使用的是Parallel Collector
#https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/parallel.html#parallel_collector_generations
#open_jdk 可以看到使用了什么GC,-XX:+UseParallelGC
并发标记,就是程序一边运行,一边标记垃圾。只有在并发的GC中才会用到
并发标记一共会有两个问题:一个是错标,标记过不是垃圾的,变成了垃圾(也叫浮动垃圾);第二个是本来已经当做垃圾了,但是又有新的引用指向它。
三色代表的意思
三色算法逻辑
假设现在有白、灰、黑三个集合(表示当前对象的颜色),其遍历访问过程为:
三色算法第一种问题: 错标
标记过不是垃圾的,变成了垃圾(也叫浮动垃圾),如下图:标记完了E是D的一个引用,也就是说此时E是灰色的,但是D断开的对E的引用。这个浮动垃圾的问题影响不是很大,可能就是暂时的浪费一点内存,它肯定抗不过下一轮GC。
三色算法第二种问题:漏标,或者叫错杀
这个问题是比较致命的,如果错杀了,就会出现运行结果不符合预期的情况。这个是绝对不能发生的。这发生的情况只有一个,就是D是黑色的,E是灰色的,但是D又指向了G,和E断开了指向G。 因为D已经标记了是黑色,但是E断开了引用,所以G就当做了是白色的。这个时候如果不操作的话,就会把G错杀掉。这种问题是必须解决掉的。
三种不同的解决错杀的方法
参考资料
(82条消息) 图文详解 三色标记算法_水的精神的博客-CSDN博客_三色标记算法
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有