JVM02——JVM垃圾回收与性能调优(下)(一)

简介: 6.垃圾回收6.1 判断垃圾6.1.1 引用计数法


标记清除可能会导致垃圾碎片过多,导致并发失败,CMS会退化为SerialOld,进行一次全面的垃圾整理。这无疑会造成很多的时间消耗,这也时CMS存在的一个问题。

6.8.5 G1垃圾回收器

JDK9的默认垃圾回收器,取代了之前的CMS垃圾回收器。

(1)垃圾回收阶段

首先是进行Young Collection,当老年代到达阈值时,进行Young Collection+ConcurrentMark,最后进行Mixed Colletion。

2)Young Collection

新创建的对象会被放入伊甸园。

当伊甸园满后(会分配总的大小)会进行Young Collection。通过复制算法将未被回收的对象移至幸存区。

当再次触发垃圾回收时,会将一部分没有被回收的幸存区对象移到老年代(达到年龄阈值),另一部分没有被回收的幸存区对象移到其他幸存区(未达到年龄阈值)。

(2)Young GC+CM(Concurrent marking)

  • 在Young GC(阶段1)的同时进行GC Root初始标记
  • 在老年代内存占用达到阈值时,会触发并发标记(无SWT)

(3)混合收集

混合收集阶段会全面收集垃圾,但是值得注意的是可以通过参数设置最大暂停时间,为了达到最大暂停时间的设置目标,老年代的内存可能不会全部进行拷贝整理,而是优先整理垃圾最多的内存。这也称其为G1的原因(Garbage First).

(4)Full GC


对于SerialGC和ParrallelGC而言,当老年代内存不足发生的垃圾回收就是full gc,但是对于CMS和G1垃圾回收器,老年代进行回收时是并发操作的,并不会造成太长的SWT,并不是full gc,G1、CMS只有当垃圾回收的速度比垃圾产生的速度要慢时,导致老年也满了,退化为SerialGC,才会触发full gc。


(5) Young Collection跨代使用


在进行young collection时,我们要查找GC Root,有一部分根对象可能在老年代中存活,新生代的对象被老年代引用了,如果我们对于整个老年代的对象进行扫描,效率肯定很低。G1垃圾回收器采取卡牌策略,把老年代的块状空间进一步划分为卡牌,当某个卡牌中的对象引用了新生代中的对象,就被标记为脏卡。在新生代内存中使用RememberSet来记录所有的引用,在查找GC Root时就可以通过RememberSet直接关注到脏卡区域,无需扫描全部老年代内存空间。当引用关系发生变化时,post-writter barrier和dirty card queue会配合更新变化的引用关系,最后通过异步线程Concurent reinforce Threads更新RememberSet。


6) Remark


通过post-writter barrier + satb_mark_queue实现。具体过程如下。


在remark阶段,我们采用黑色表示已经完成mark处理的对象,用灰色表示正在进行remark操作的对象,用白色表示还未进行remark操作的对象。如下图,A已经完成mark,并且其被强引用,故不会被垃圾回收,B正在remark,C尚未开始mark。

如果B完成Remark,在对C进行mark时恰B与C的引用断开(标记阶段垃圾回收线程与用户线程是并发的),那么C就会被标记成为白色。如果在后面A又引用了C,那么垃圾回收时,C对象会被回收吗?答案当然是不会。这是因为当C对象被引用时,会执行post-writter barrier,并将C对象放入satb_mark_queue,置为灰色。在进行remark时,会对satb_mark_queue中的对象进行扫描,如扫描到被引用,则会将其置为黑色。

(7)字符串去重


在jdk8中,string字符串是存放在char数组中,如果通过new String的方式创建可能会导致重复创建。除了通过intern()方法来避免重复创建的发生,G1垃圾回收器会在新生代回收时并发检查是否存在重复创建的字符串,如果有则让他们指向同一个char数组。使用-XX: +UseStringDeduplication可以开启字符串去重(默认打开)。


(8)类卸载


在jdk8u40后,所有对象在经过并发标记后,就可以知道哪些类不再被使用,当一个类加载器所有的类都不再被使用后(主要是框架、自定义类加载器),就会尝试对这些类进行类卸载。使用-XX:+ClassUnloadConcurrentWithMark可以开启类卸载(默认开启)。

目录
打赏
0
0
0
0
4
分享
相关文章
CMS圣经:CMS垃圾回收器的原理、调优,多标+漏标+浮动垃圾 分析与 研究
本文介绍了CMS(Concurrent Mark-Sweep)垃圾回收器的工作原理、优缺点及常见问题,并通过具体案例分析了其优化策略。重点探讨了CMS的各个阶段,包括标记、并发清理和重标记
CMS圣经:CMS垃圾回收器的原理、调优,多标+漏标+浮动垃圾 分析与 研究
JVM实战—4.JVM垃圾回收器的原理和调优
本文详细探讨了JVM垃圾回收机制,包括新生代ParNew和老年代CMS垃圾回收器的工作原理与优化方法。内容涵盖ParNew的多线程特性、默认线程数设置及适用场景,CMS的四个阶段(初始标记、并发标记、重新标记、并发清理)及其性能分析,以及如何通过合理分配内存区域、调整参数(如-XX:SurvivorRatio、-XX:MaxTenuringThreshold等)来优化垃圾回收。此外,还结合电商大促案例,分析了系统高峰期的内存使用模型,并总结了YGC和FGC的触发条件与优化策略。最后,针对常见问题进行了汇总解答,强调了基于系统运行模型进行JVM参数调优的重要性。
JVM实战—4.JVM垃圾回收器的原理和调优
JVM简介—2.垃圾回收器和内存分配策略
本文介绍了Java垃圾回收机制的多个方面,包括垃圾回收概述、对象存活判断、引用类型介绍、垃圾收集算法、垃圾收集器设计、具体垃圾回收器详情、Stop The World现象、内存分配与回收策略、新生代配置演示、内存泄漏和溢出问题以及JDK提供的相关工具。
JVM简介—2.垃圾回收器和内存分配策略
JVM实战—3.JVM垃圾回收的算法和全流程
本文详细介绍了JVM内存管理与垃圾回收机制,涵盖以下内容:对象何时被垃圾回收、垃圾回收算法及其优劣、新生代和老年代的垃圾回收算法、Stop the World问题分析、核心流程梳理。
JVM实战—3.JVM垃圾回收的算法和全流程
JVM实战—5.G1垃圾回收器的原理和调优
本文详细解析了G1垃圾回收器的工作原理及其优化方法。首先介绍了G1通过将堆内存划分为多个Region实现分代回收,有效减少停顿时间,并可通过参数设置控制GC停顿时长。接着分析了G1相较于传统GC的优势,如停顿时间可控、大对象不进入老年代等。还探讨了如何合理设置G1参数以优化性能,包括调整新生代与老年代比例、控制GC频率及避免Full GC。最后结合实际案例说明了G1在大内存场景和对延迟敏感业务中的应用价值,同时解答了关于内存碎片、Region划分对性能影响等问题。
JVM简介—1.Java内存区域
本文详细介绍了Java虚拟机运行时数据区的各个方面,包括其定义、类型(如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和直接内存)及其作用。文中还探讨了各版本内存区域的变化、直接内存的使用、从线程角度分析Java内存区域、堆与栈的区别、对象创建步骤、对象内存布局及访问定位,并通过实例说明了常见内存溢出问题的原因和表现形式。这些内容帮助开发者深入理解Java内存管理机制,优化应用程序性能并解决潜在的内存问题。
130 29
JVM简介—1.Java内存区域
快速定位并优化CPU 与 JVM 内存性能瓶颈
本文介绍了 Java 应用常见的 CPU & JVM 内存热点原因及优化思路。
678 166
JVM实战—2.JVM内存设置与对象分配流转
本文详细介绍了JVM内存管理的相关知识,包括:JVM内存划分原理、对象分配与流转、线上系统JVM内存设置、JVM参数优化、问题汇总。
JVM实战—2.JVM内存设置与对象分配流转
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
882 1