作品标明出处:本文是对《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》阅读后的整理,有兴趣的同学可购买正版进行学习!
1.查看JVM默认垃圾收集器
java -XX:+PrintCommandLineFlags -version
上图中的 -XX:+UseParallelGC就是我们默认使用的收集器,新生代使用的是Parallel Scanvenge收集器,老年代使用的是Serial Old
2.JVM垃圾收集器常用参数
3.垃圾收集器
如果两个收集器之间存在连线,就说明它们可以搭配使用 ,图中收集器所处的区域,则表示它是属于新生代收集器抑或是老年代收集器
- Serial收集器
新生代收集器,低延迟
单线程收集器:不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束,Stop The World!
-
ParNew收集器
新生代收集器
是Serial收集器的多线程并行版本。
只有它能和CMS收集器搭配使用。
ParNew收集器是激活CMS后(使用-XX:+UseConcMarkSweepGC选项)的默认新生代收集器,也可以使用-XX:+/-UseParNewGC选项来强制指定或者禁用它。
- Parallel Scanvenge收集器
新生代收集器,标记--复制算法
和ParNew收集器非常相似,目标是达到一个可控制的吞吐量
参数 -XX:+UseAdaptiveSizePolicy,垃圾收集的自适应调节策略,不需要人工指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象大小(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量
- Serial Old收集器
老年代单线程收集器,标记--整理算法
两种用途:
1、在JDK 5以及之前的版本中与Parallel Scavenge收集器搭配使用
2、作为CMS收集器发生失败时的后备预案,在并发收集发生Concurrent Mode Failure时使用
.
- Parallel Old收集器
老年代多线程收集器,标记--整理算法
Parallel Scavenge + Parallel Old收集器搭配使用,吞吐量优先
- CMS收集器(Concurrent Mark Sweep)
老年代多线程收集器,标记--清除算法(收集结束可能会导致大量空间碎片,触发Full GC)
并发收集、低延迟,“并发低停顿收集器”(Concurrent Low Pause Collector)
整个过程分为四个步骤:
1、初始标记(CMS initial mark)
2、并发标记(CMS concurrent mark)
3、重新标记(CMS remark)
4、并发清除(CMS concurrent sweep)
JDK5默认启动阈值为老年代使用了 68%,
JDK6时默认阈值提升至92%,此时可能导致CMS运行期间预留的内存无法满足程序分配新对象的需要,就会出现一次“并发失败”(Concurrent Mode Failure),这时候虚拟机将不得不启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来重新进行老年代的垃圾收集
- G1(Garbage First)收集器
面向整个堆空间多线程收集器,标记--整理算法,每个Region又是基于标记--复制算法
低延迟、
JDK9以后默认垃圾收集器
面向局部收集、基于Region内存布局
面向堆内存任何部分来组成回收集,衡量标准为哪块内存中存放的垃圾最多,会后收益最大,这就是G1收集器的Mixed GC模式
G1把连续的Java堆划分为多个大小相等的独立区域Region,每个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间;Region中还有一类特殊的Humongous区域,专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象
每个Region大小可以通过参数-XX:G1HeapRegionSize设定,取值范围为1MB~32MB,且应为2的N次幂
而对于那些超过了整个Region容量的超级大对象,将会被存放在N个连续的Humongous Region之中,G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待
Region里面存在的跨Region引用对象如何解决?
答:使用记忆集避免全堆作为GC Roots扫描,每个Region都维护有自己的记忆集,这些记忆集会记录下别的Region指向自己的指针,并标记这些指针分别在哪些卡页的范围之内。
由于Region数量比传统收集器的分代数量明显要多得多,因此G1收集器要比其他的传统垃圾收集器有着更高的内存占用负担。根据经验,G1至少要耗费大约相当于Java堆容量10%至20%的额外内存来维持收集器工作
G1收集器的四个步骤:
1、初始标记(Initial Marking)
2、并发标记(Concurrent Marking)
3、最终标记(Final Marking)
4、筛选回收(Live Data Counting and Evacuation)
- Shenandoah收集器
低延迟、并发收集,标记--整理算法
也是基于Region的堆内存布局,同样有着用于存放大对象的Humongous Region,默认的回收策略也同样是优先处理回收价值最大的Region
Shenandoah(目前)是默认不使用分代收集,不会有专门的新生代Region或者老年代Region的存在,没有实现分代
Shenandoah摒弃了在G1中耗费大量内存和计算资源去维护的记忆集,改用名为“连接矩阵”(ConnectionMatrix)的全局数据结构来记录跨Region的引用关系,降低了处理跨代指针时的记忆集维护消耗,也降低了伪共享问题的发生概率
Shenandoah收集器的工作过程大致可以划分为以下九个阶段:
1、初始标记(Initial Marking)
2、并发标记(Concurrent Marking)
3、最终标记(Final Marking)
4、并发清理(Concurrent Cleanup)
5、并发回收(Concurrent Evacuation)
6、初始引用更新(Initial Update Reference)
7、并发引用更新(Concurrent Update Reference)
8、最终引用更新(Final Update Reference)
9、并发清理(Concurrent Cleanup)
- ZGC
低延迟垃圾收集器,基于Region内存布局,并发标记-整理算法
ZGC的Region具有动态性——动态创建和销毁
在x64硬件平台下,ZGC的Region可以具有如图3-19所示的大、中、小三类容量:
1、小型Region(Small Region):容量固定为2MB,用于放置小于256KB的小对象。
2、中型Region(Medium Region):容量固定为32MB,用于放置大于等于256KB但小于4MB的对象。
3、大型Region(Large Region):容量不固定,可以动态变化,但必须为2MB的整数倍,用于放置4MB或以上的大对象。每个大型Region中只会存放一个大对象
ZGC收集器的运作过程:
1、并发标记(Concurrent Mark)
2、并发预备重分配(Concurrent Prepare for Relocate)
3、并发重分配(Concurrent Relocate)
4、并发重映射(Concurrent Remap)