Java高阶私房菜:JVM分代收集算法介绍和各垃圾收集器原理分解
目录
什么是分代收集算法
GC的分类和专业术语
什么是垃圾收集器
垃圾收集器的分类及组合
编辑
应关注的核心指标
Serial和ParNew收集器原理
Serial收集器
ParNew收集器
Parallel和CMS收集器原理
Parallel 收集器
CMS收集器
新一代垃圾收集器G1和ZGC
G1垃圾收集器
回收原理讲解
三种垃圾回收模式
MixGC垃圾回收步骤
常见参数讲解
配置注意事项
ZGC-新一代垃圾搜集器
什么是ZGC
工作流程
平台支持说明
验证参数(JDK17环境)
关于升级建议
现在市面上充斥着许多对于JVM垃圾收集器教程,有零基础的,有专讲的 ... 这些教程或文章大都长篇大论的细扣字眼,内容繁多且没有重点,看过便会忘,本篇集结了9年老JAVA工作及面试经验,专讲面试和工作中使用到的,一站式讲解,帮助你疏通学习脉络,少走弯路。
学习本章节前,对于垃圾回收机制还不了解的话可以看看我的上篇文章进行回顾。传送门:Java高阶私房菜:JVM垃圾回收机制及算法原理探究-CSDN博客
什么是分代收集算法
针对不同生命周期的对象采用不同的垃圾回收策略,以达到更好的垃圾回收效果。年轻代空间多数对象存活时间短,可以高频地进行回收;而在老年代空间多数对象存活时间久,则需要低频回收。分代算法是根据回收对象的特点进行选择,根据上篇总结,年轻代适合标记-复制算法,老年代适合标记清除或标记压缩算法,通过将内存划分为不同的代,可以使得Minor GC的频率更高,更早地回收垃圾对象,减少Full GC的发生频率,提高整体性能。
JVM将内存分为年轻代和老年代,其中年轻代又分为Eden区和两个Survivor区。
年轻代:用于存放新生的对象,其中Eden区是新对象的分配区域,当Eden区满时,会触发Minor GC,将存活的对象移动到Survivor区,同时清空Eden区,Survivor区则用于存放经过一次Minor GC后存活的对象。
老年代:用于存放长时间存活的对象,当年轻代中的对象经过多次Minor GC后仍然存活,就会被移动到老年代,当老年代满时,会触发Full GC。
GC的分类和专业术语
Partical GC(部分收集)
新生代收集:对象从Young 区域消失(被回收)的过程称为“minor GC / Young GC”,Eden 的清理,S0\S1的清理都由于MinorGC,当YoungGen区内存不足时,就会触发minorGC。
老年代收集:对象从老年代中消失的过程,清理整合OldGen的内存空间,称为“Major GC/Old GC”,有些垃圾收集器 针对老年代单独回收,所以比较少用
Full GC(整堆收集)
清理整个堆空间,包括年轻代和老年代,可以理解为Major GC+Minor GC组合后进行的一整个过程,是清理JVM整个堆空间。
其实不用过多关心是叫Major GC还是Full GC,应该关注当前的 GC是否停止了所有应用程序的线程,许多Major GC 是由 Minor GC 触发的, 出现 Major GC通常出现至少一次的Minor GCMajorGC 的速度一般要比Minor GC慢 10倍不止。
其可手动调用System.gc( )触发, 但却不一定会立马执行Full GC,而只是提交了一个回收请求,由JVM的自动垃圾回收机制判断当前是否触发Full GC,即当老年代空间不足 , 通过Minor GC后进入老年代的平均大小大于老年代的可用内存。
需要注意的是,当执行Full GC时,它会暂停所有当前的应用线程,时间由回收效率而定,直至整个垃圾回收过程完成才恢复正常,它对系统的性能有较大影响,所以在生产环境中要尽量避免使用该方法,可以通过启动参数-XX:+ DisableExplicitGC来禁止调用System.gc()。内存的优化则尽量利用JVM垃圾回收策略来维护,包括日常的编码中不再使用的变量要置Null切断与堆空间的联系。
STW(Stop The World)
垃圾回收发生过程中,用户线程在运行至安全点(safe point)后,就自行挂起进入暂停状态,对外的表现就是卡顿,所以应尽量减少Full GC的次数,是Minor GC还是Major GC都会STW,区别只在于STW的时间长短。
JVM资料很多,有讲32位和64位的的虚拟机的参数,但是基本都不用32位操作系统(生产环境更是如此,如果仍使用32位操作系统就应该反省在这家公司的去留问题了),所以不用花时间去了解32位的。
什么是垃圾收集器
还是那句话,垃圾回收算法是内存回收的方法论,垃圾收集器则是内存回收的具体实现,目前Java规范中并没有对垃圾收集器的实现有任何规范,不同的厂商、不同的版本的虚拟机提供的垃圾收集器是不同的,主要讨论的是HotSpot虚拟机。
那么有没有最厉害的垃圾收集器呢?负责任的说其实不存在最厉害的垃圾收集器,只有在对应场景中最合适的垃圾收集器。
那为什么要有这么多的收集器呢?那是因为Java的使用场景很多,移动端,服务器等,然后内存里面对象存活时间不一样,需要针对不同的场景,提供不同的垃圾收集器,提高垃圾收集的性能。
垃圾收集器的分类及组合
新生代收集器
-
Serial 串行垃圾收集器
-
ParNew 年轻代的并行垃圾回收器
-
Parallel 并行垃圾收集器
老年代收集器
-
Serial Old 串行老年代垃圾器
-
Parallel Old 老年代的并行垃圾回收器
-
CMS (ConcMarkSweep)并发标记清除
整堆收集器:
G1:JDK9的默认垃圾收集器,以替代CMS。该收集器指出新生代和老年代不再是物理隔离的了(但还保留着新生代和老年代的概念),它们都是一部分Region (不需要连续)的集合,通过Region的动态分配方式实现逻辑上的连续。
ZGC:JDK11新引入的ZGC收集器,在该收集器中不管是物理上还是逻辑上,已经不存在新老年代的概念了,它们会被分为一个个page,当进行GC操作时会对page进行压缩,因此没有碎片问题。
那么那么多垃圾收集器,我们是否都要记住?作为新时代互联网人,还是那句话,我们只学有用的,淘汰的垃圾收集器我们不花太多时间。
垃圾收集器的组合
两个垃圾收集器之间如果存在连线,则说明它们可以搭配使用,图中:Serial old作为CMS出现"Concurrent Mode Failure"失败的后备预案
这里需要注意的是:
-
JDK8中默认使用: Parallel Scavenge GC + ParallelOld GC
-
JDK14 弃用了: Parallel Scavenge GC + Parallel OldGC
-
JDK9默认是用G1为垃圾收集器
-
JDK14 移除了 CMS GC
查看默认垃圾收集器
JVM参数: -XX:+PrintCommandLineFlags 查看命令行相关参数(包含使用的垃圾收集器)
设置默认垃圾收集器
// JDK8-XX:InitialHeapSize=536870912 -XX:MaxHeapSize=8589934592 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC // JDK11-XX:G1ConcRefinementThreads=9 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=8589934592 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC // JDK17-XX:ConcGCThreads=2 -XX:G1ConcRefinementThreads=9 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=536870912 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=8589934592 -XX:MinHeapSize=6815736 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
应关注的核心指标
吞吐量:运行用户代码的时间占总运行时间的比例(总运行时间 = 程序的运行时间 + 内存回收的时间),例如:虚拟机共运行100分钟,垃圾收集器花掉1分钟,那么吞吐量就是99%。
暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间,一个时间段内应用程序线程暂停,让GC线程执行的状态,GC期间100毫秒的暂停时间,说明在这100毫秒期间内没有应用程序线程是活动的。
收集频率:指垃圾回收器多长时间会运行一次。一般来说,垃圾回收器的频率应该是越低越好。
Serial和ParNew收集器原理
Serial收集器
它作为最简单的垃圾收集器,使用单线程进行垃圾收集,暂停所有应用程序线程, 在单核CPU环境来说,Serial收集器是更高效的。Serial Old是Serial收集器的老年代版本,在jdk1.5之前的版本与Parallel收集器搭配使用,或者作为CMS的备选方案。它适用于小型应用程序和客户端应用程序,一般javaweb、springboot项目不会采用这类收集器。
其实现算法视区域的不同:新生代采用复制算法,老年代采用标记整理算法
相关命令参数使用
-
同时指定年轻代和老年代都使用串行垃圾收集器
-XX:+UseSerialGC
-
查看命令行相关参数
-XX:+PrintCommandLineFlags
-
全部参数 (JDK11环境)
//参数
-XX:+UseSerialGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m//输出
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC
ParNew收集器
工作在年轻代上的,只是将串行的垃圾收集器改为了并行,其他基本和Serial一样,使用多个线程进行垃圾回收的,适用于大型应用程序和多核处理器,以及在服务端应用程序中使用,单核上效率比Serial低,和下集讲Parallel收集器类似,但Parallel收集器不兼容CMS,除了它只有Serial收集器可以和CMS收集器配合工作。
其实现算法视区域的不同:新生代采用复制算法,老年代采用标记整理算法
相关命令参数使用
-
年轻代使用ParNew回收器,老年代使用串行收集器
-XX:+UseParNewGC
-
查看命令行相关参数
-XX:+PrintCommandLineFlags
-
验证参数 (JDK8环境,如果用JDK11会报错,JDK8开始已经不再被推荐使用)
//参数
-XX:+UseParNewGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m//输出
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParNewGC Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release
Parallel和CMS收集器原理
Parallel 收集器
全称 Parallel Scavenge 是一种多线程垃圾收集器,和ParNew收集器类似,是一个新生代收集器,默认线程数和cpu核数一样,用于大型应用程序和服务器应用程序,比如大批量数据处理,后台计算任务等,Parallel Old是Parallel Scavenge收集器的老年代版本,JDK8默认使用Parallel Scavenge收集器。
其实现算法视区域的不同:新生代采用复制算法,老年代采用标记整理算法
Parallel对比ParNew
-
-XX:+UseParallelGC 仅对年轻代有效,不可以和CMS收集同时使用
-
-XX:+UseParNewGC 设置年轻代为多线程收集,可以和CMS收集同时使用
相关命令参数使用
-
年轻代使用ParallelGC垃圾回收器,老年代使用串行回收器
-XX:+UseParallelGC
-
年轻代使用ParallelGC垃圾回收器,老年代使用ParallelOldGC垃圾回收器
-XX:+UseParallelOldGC
-
查看命令行相关参数
-XX:+PrintCommandLineFlags
-
验证参数(JDK11环境)
//参数一
-XX:+UseParallelGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m//输出
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC //参数二
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m//输出
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC -XX:+UseParallelOldGC
CMS收集器
全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,老年代中的对象生命周期较长,垃圾回收频率较低,目标是获取最短垃圾收集停顿时间,针对 老年代 垃圾的收集器,停顿时间较短,适合对响应时间要求较高的应用程序,如Web应用程序、电子商务等高并发场景。
整个过程分4步(初始标记 和 重新标记 需要stopTheWorld,并发标记与并发清除阶段不需要暂停用户线程)
-
初始标记: 标记GC Root直接关联对象,会导致stopTheWorld
-
并发标记: 与用户线程同时运行
-
重新标记:会导致stopTheWorld
-
并发清除:与用户线程同时运行
相关命令参数使用
-
年轻代使用ParNew垃圾回收器,老年代使用CMS回收器
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
-
查看命令行相关参数
-XX:+PrintCommandLineFlags
-
验证参数(JDK11环境,然后被弃用了,验证成功需要用JDK8)
//输入
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m//输出
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:MaxNewSize=11190272 -XX:MaxTenuringThreshold=6 -XX:NewSize=11190272 -XX:OldSize=22364160 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC //警告信息Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
上述垃圾收集器都是接近被弃用了,大体了解即可,重点掌握接下去的G1和ZGC
新一代垃圾收集器G1和ZGC
G1垃圾收集器
回收原理讲解
Garbage First 垃圾收集器是JDK7版本之后引入的一种垃圾回收器,Jdk9中将G1变成默认的垃圾收集器,可以在不同的内存区域中分配垃圾回收的工作,提高了垃圾回收效率。
它保留了分代思想,把内存划分为多个独立的区域Region,区域中包含逻辑上的年轻代、老年代区域。取消了年轻代、老年代的物理划分,不用单独对每个年代空间进行设置。Region的区域类型是动态变化的,可能之前是年轻代,经过了垃圾回收之后就变成了老年代,实现更加精细化的垃圾回收。整体采用标记整理算法, 局部是采用复制算法,不会产生内存碎片。它把整个Java堆划分成约2048个独立Region块,每个Region块大小根据堆空间的大小而定,为2的N次幂,1MB~32MB,即每个Region的大小可通过参数 -XX:G1HeapRegionSize
配置
新增加一种叫Humongous内存区域,用于存储大对象,它规定如果超过1.5个region,就是巨型对象,就放到H区,默认直接会被分配在老年代,一般被视为老年代.图中的H块,如果一个H区装不下一个巨型对象,G1会寻找连续的H区来存储,为了能找到连续的H区,有时需要启动Full GC。
相关命令参数使用
-
查看默认垃圾收集器
-XX:+PrintCommandLineFlags
查看命令行相关参数(包含使用的垃圾收集器)
//JDK11-XX:G1ConcRefinementThreads=9 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=536870912 -XX:MaxHeapSize=8589934592 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
三种垃圾回收模式
Young GC
G1与之前垃圾收集器的Young GC
不同,不是当新生代的Eden区放满了就进行垃圾回收,G1会计算当前Eden区回收大概需要多久时间,如果接近参数-XX:MaxGCPauseMills
设定的值,便会触发Young GC。
回收过程也是将Eden区和Survivor区中的存活对象复制到空闲的Survivor区,并清空Eden区和原来的Survivor区。如果Survivor区也满了,那么会将存活对象复制到Old区,在Young GC期间,应用程序会被暂停。
Mixed GC
多数对象晋升到老年代old region时,为了避免堆内存被耗尽问题,会触发混合的GC。回收整个Young Region,还会回收一部分的Old Region区域,注意不是全部Old Region区域。其触发条件由配置的参数 -XX:InitiatingHeapOccupancyPercent=n决定。默认为45%,即 当老年代大小占整个堆大小百分比达到该阀值时触发。
Full GC
单个线程会对整个堆的所有代中所有分区做标记、清除以及压缩动作,非常耗时。
总结
在Young GC和Mixed GC中,G1垃圾收集器都会对每个Region的存活对象数量进行统计,根据存活对象数量和空闲Region的数量,动态地决定垃圾收集的区域和顺序,这种动态的垃圾收集策略,可以避免Full GC的发生,提高了应用程序的响应速度。
MixGC垃圾回收步骤
1)初始标记(STW):记录下GC Roots能直接引用的对象,并标记所有存活的对象,会执行一次年轻代GC,需要暂停所有线程,速度很快。
2)并发标记:与应用线程一起工作,进行可达性分析,G1收集器会对堆内存进行并发标记,找出所有存活的对象,并记录它们所在的Region.
3)最终标记(STW):修正并发标记期间, 部分因程序运行导致发生变化的那一部分对象,根据算法修复一些引用的状态;
4)筛选回收(STW):对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿STW时间,即-XX:MaxGCPauseMillis
制定计划。
这里举一个成本排序案例,现在有Region1、Region2和Region3三个区域:
1)Region1预计可以回收1.5MB内存,预计耗时2MS,投产比ROI=1.5/2;
2)Region2预计可以回收1MB内存,预计耗时1MS,投产比ROI=1/1;
3)Region3预计可以回收0.5MB内存,预计耗时1MS,投产比ROI=0.5/1;
那Region1、Region2和Region3各自的回收价值与成本比值分别是:0.75、1和0.5,比值越高说明同样的付出收益越高,如果此时只能回收一个Region的内存空间,G1就会选择Region2进行回收,保证了G1收集器在有限的时间内尽可能地提高收集效率。
常见参数讲解
G1的使用方式非常的简单,只需对应开启G1垃圾收集器,配置堆最大内容及最大停顿时间便可享受到。一个搞笑的事情是在职场中,很大可能工龄十多年的老手花大半月时间去调优一次JVM参数,还不如直接升级JDK来的性能高,当然这也只是当成一个笑点,但这侧面也能看出来升级JDK的性价比,当然如果能掌握JDK,两者结合在一起加以利用能发挥它的最大效能。
相关参数
- -XX:+UseG1GC:启用G1垃圾收集器。
- -XX:G1HeapRegionSize=n:Java 堆大小划 分出约 2048 个区域,默认是堆内存的1/2000;配置需要为2的N次幂,1MB~32MB,使用G1垃圾回收器最小堆内存应为 1MB*2048=2GB ,低于这个的建议使用其它垃圾回收器。
- -XX:MaxGCPauseMillis=n:设置最大停顿时间,单位为毫秒,默认为200毫秒(JVM会尽力实现,但不能保证达到)
- -XX:ParallelGCThreads=n:设置 STW 工作线程数的值。一般设置为逻辑处理器的数量,最多为 8,是在STW阶段,并行执行【垃圾收集动作】的线程数
- -XX:ConcGCThreads=n:在【并发标记】阶段,并发执行标记的线程数,一般将 n 设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4
- -XX:InitiatingHeapOccupancyPercent=n:设置G1 Mix垃圾回收的触发阈值,默认为45%
命令案例
//输入
-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -Xms524m -Xmx524m -XX:+PrintCommandLineFlags //输出
-XX:G1ConcRefinementThreads=9 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=549453824 -XX:MaxGCPauseMillis=100 -XX:MaxHeapSize=549453824 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
使用场景
- 大型应用程序:可以将堆内存划分为多个区域,以实现更加精细化的垃圾回收。
- 高并发、低延迟:对响应时间要求较高的应用程序,如Web应用程序、电子商务等高并发场景。
- 大内存应用:可以在垃圾回收过程中释放大量的空间,提高了内存的利用率。
配置注意事项
-
不手工设置年轻代大小,比如使用 -Xmn 选项或 -XX:NewRatio 等设置年轻代大小
-
暂停时间的目标不要太小,G1 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间。如果把停顿时间调得非常低,如设置为10毫秒,很可能出现的结果就是由于停顿目标时间太短,导致每次回收内存只占堆内存很小的一部分, 收集器收集的速度跟不上分配器分配的速度, 导致垃圾慢慢堆积。应用运行时间一长就占满堆引发Full GC反而降低性能, 通常把期望停顿时间设置为一两百毫秒是比较合理的
-
避免存活时间短的大对象:G1垃圾收集器对程序的代码质量要求较高,需要对程序的内存使用情况进行精细化管理,对应用程序的代码进行优化和调整
ZGC-新一代垃圾搜集器
什么是ZGC
Z Garbage Collector 是Oracle公司开发一种可伸缩、低停顿时间的垃圾收集器,标记-复制算法(进行了改进)。垃圾回收过程几乎全部是并发,实际STW停顿时间极短,停顿时间控制10ms内,主要采用的染色指针和读屏障技术。
在 JDK 11 中是实验性的特性引入,在 JDK 15 中 ZGC 可以正式投入生产使用,使用 –XX:+UseZGC 启用,ZGC 的堆内存也是基于 Region 来分布,和G1类似,但不再区分新生代老年代的,Region 支持动态地创建和销毁,大小不是固定。
有三种类型的 Region
- 小型页面 Small Region:容量固定2MB,主要用于放置小于 256 KB 的小对象。
- 中型页面Medium Region:容量固定32MB,主要用于放置大于等于 256 KB 小于 4 MB 的对象。
- 大型页面Large Region:容量不固定 为N * 2MB, Region 是可以动态变化的,但必须是 2MB 的整数倍,最小支持 4 MB。
垃圾回收特点
-
低停顿时间:ZGC最大的特点是在不增加延迟的情况下,能够处理非常大的内存数据,可以将停顿时间限制在10ms以内,对于需要快速响应的应用程序来说是非常重要;
-
可伸缩性:可以处理非常大的内存数据,适应不同规模的应用程序,从小型应用程序到大型企业级应用程序;
-
不需要分代:不需要将内存分为新生代和老年代,不需要复杂的内存回收算法;
-
并发处理:采用了并发处理的方式来进行垃圾回收可以在应用程序运行的同时进行垃圾回收;
工作流程
-
初始标记(STW):找 GC Roots 直接引用的对象,处理时间和GC Roots的数量成正比,停顿时间不随着堆的大小而增加;
-
并发标记(没有STW):扫描剩余的所有对象,处理时间比较长,业务线程与GC线程同时运行,但这个阶段会有漏标问题;
-
再标记(STW):通过算法解决漏标对象,和G1中的解决漏标的算法类似;
-
并发转移准备(没有STW) :分析最有回收价值GC分页,即ROI计算;
-
初始转移(STW):转移初始标记的存活对象和做对象重定位,时间和GC Roots的数量成正比,时间不随堆的大小而增加;
-
并发转移(没有STW):对转移并发标记的存活对象做转移;
平台支持说明
部分版本里面是实验性参数,需要加 -XX:+UnlockExperimentalVMOptions
才可以使用
平台 | 是否支持 | 支持版本 |
---|---|---|
Linux/x64 | 是 | JDK 15 (Experimental since JDK 11) |
Linux/AArch64 | 是 | JDK 15 (Experimental since JDK 13) |
macOS/x64 | 是 | JDK 15 (Experimental since JDK 14) |
Windows/x64 | 是 | JDK 15 (Experimental since JDK 14) |
Windows/AArch64 | 是 | JDK 16 |
macOS/AArch64 | 是 | JDK 17 |
Linux/PowerPC | 是 | JDK 18 |
验证参数(JDK17环境)
参数: -XX:+UseZGC -XX:+PrintCommandLineFlags -Xms32m -Xmx32m输出结果
-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:MinHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:-UseCompressedOops -XX:+UseZGC
关于升级建议
ZGC业界还没大规模使用,更多在实验性观望阶段,还存在变动和争议阶段,如果可能则预计26年~28年成为主流;当下我们开发的采用的垃圾收集器是G1收集器,23~25年会是主流。
大家使用的话可以升级JDK,在JDK 11中首次支持ZGC,且JDK 11属于长期支持(Long Term Support,LTS)版本,Linux平台下JDK11开始支持ZGC,JDK14开始支持Mac和Windows。
JVM调优中,升级JDK版本有较大收益,但是风险需要评估好。通常从兼容性和功能模块和性能风险进行评估。
- 兼容性和功能模块:程序依赖很多三方jar包,有些jdk升级会把旧的API直接移除,导致项目直接编译不通过,版本升级,有些潜在的功能逻辑可能会被调整,导致些不可预测的故障产生,尤其是接锅侠身上;
- 性能风险:短期测试相关数据是比较优,但是也需要能保持性能稳定。常规建议技术团队可以预发布环境进行稳定性测试,基于生产环境流量拷贝;
学习资料拓展:https://wiki.openjdk.org/display/zgc
相关文章:
Java高阶私房菜:JVM分代收集算法介绍和各垃圾收集器原理分解
目录 什么是分代收集算法 GC的分类和专业术语 什么是垃圾收集器 垃圾收集器的分类及组合 编辑 应关注的核心指标 Serial和ParNew收集器原理 Serial收集器 ParNew收集器 Parallel和CMS收集器原理 Parallel 收集器 CMS收集器 新一代垃圾收集器G1和ZGC G1垃圾收集器…...
为什么IB损失要在100epochs后再用?
在给定的代码中,参数start_ib_epoch用于控制从第几轮开始使用IB(Instance-Balanced)损失函数进行训练。具体来说,如果start_ib_epoch的值大于等于100,那么在训练的前100轮中将使用普通的交叉熵损失函数(CE&…...
《Video Mamba Suite》论文笔记(4)Mamba在时空建模中的作用
原文翻译 4.4 Mamba for Spatial-Temporal Modeling Tasks and datasets.最后,我们评估了 Mamba 的时空建模能力。与之前的小节类似,我们在 Epic-Kitchens-100 数据集 [13] 上评估模型在zero-shot多实例检索中的性能。 Baseline and competitor.ViViT…...
【备战软考(嵌入式系统设计师)】10 - 软件工程基础
这一部分的内容是概念比较多,不要理解,去感受。 涉及的知识点是嵌入式系统开发和维护的部分,也就是和管理相关的,而不是具体如何进行嵌入式系统开发的细节。 系统开发生命周期 按照顺序有下面几个阶段,我们主要要记…...
随手笔记-GNN(朴素图神经网络)
自己看代码随手写的一点备忘录,自己看的,不喜勿喷 GNN (《------ 代码) 刚开始我还在怀疑为什么没有加weigth bias,已经为什么权重才两个,原来是对node_feats进行的network的传播,而且自己内部直接进行了。 下面是一…...
C 语言指针怎么理解?
在今天的学习中,我注意到有位学员似乎对 C 语言指针的理解有些困惑。为了帮助大家更好地理解,我来举个例子。 C 语言指针就好比 Windows 桌面上常见的快捷方式。快捷方式可以指向某个游戏,这就是普通指针;它也可以指向另一个快捷…...
HTTP协议:通信机制、特点及实践应用
目录 前言 1. 运行机制 2. 通信方式 3. 主要特点 4. 统一资源标识符(URL) 5. HTTP报文 6. HTTP请求 7. HTTP响应 8. 实体 9. 持续连接 结语 前言 HTTP(Hypertext Transfer Protocol)是互联网上应用最广泛的一种协议&a…...
Leetcode—289. 生命游戏【中等】
2024每日刷题(126) Leetcode—289. 生命游戏 算法思想 实现代码 class Solution { public:void gameOfLife(vector<vector<int>>& board) {int rows board.size();int cols board[0].size();int neighbors[3] {0, 1, -1};vector<…...
系统运维(虚拟化)
1.VLAN VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。 每个VLAN是一个广播域,VLAN内的主机间可以直接通信,而VLAN间则不能直接互通。这样,广播报…...
Linux域名解析
1.hosts:windows c盘下面 Linux: /etc/hosts 作用:实现名字解析,主要为本地主机名、集群节点提供快速解析。平面式结构,集中式数据库。 缺点:不便于查询更新 2.DNS:域名系统 作用:实现名字解析(分层性,层次性) FQDN:完全合格域名/全称域…...
树形结构和列表的区别
树形结构和列表在数据组织、表示方式以及应用场景等方面存在明显的区别。 首先,树形结构是一种非线性的数据结构,表现为层次的嵌套结构。每个节点可以有多个子节点,这些子节点又可以有自己的子节点,形成一个层次分明的结构。这种一…...
Go中json的解析和反解析
在解析过程中,反向解析不包含其中的部分参数也不会报错,这是需要注意的一点 31 func main() { // E: main redeclared in this block 32 type A…...
SpringBoot+vue实现退出功能
目录 1. 创建点击事件 2. 编写退出逻辑 在Spring Boot 和 Vue.js 应用中实现退出功能,通常涉及到前端的用户界面操作和注销逻辑。 以下是实现退出功能的步骤: 1. 创建点击事件 在header.vue中创建一个点击事件 <span style"text-decoratio…...
Linux操作系统中管理磁盘的另外一种操作方式。即LVM——逻辑卷管理操作
在Linux操作系统中管理磁盘的一种方法名称——LVM,这种管理磁盘的优势。 1.使用LVM去管理磁盘可以在不影响原来数据的前提下去扩容磁盘空间或者是缩减磁盘空间。 在LVM中除了上层逻辑券可以扩容,下层的券组也可以扩容。 2.使用LVM管理的磁盘支持快照功…...
Lua 零基础入门
Lua 1.Lua是什么? 1.1 Lua的历史 Lua是由Roberto Ierusalimschy、Luiz Henrique de Figueiredo和Waldemar Celes于1993年创建的,当时他们是巴西里约热内卢天主教大学计算机图形技术组(Tecgraf)的成员。在开发Lua之前࿰…...
记录DemoApplication.java不变蓝问题
问题 解决方案 一、点击右下角加载 二、右键项目 勾选maven...
22_Scala集合Seq
文章目录 Seq序列1.构建集合2.List集合元素拼接&&集合拼接3.可变Seq&&List3.1 ListBuffer创建3.2 增删改查3.3 相互转化 Appendix1.Scala起别名2.Seq底层3.关于运算符操作: :4.空集合的表示 Seq序列 –Seq表示有序,数据可重复的集合 1.构建集合 …...
机器学习初学者 6 个核心算法!建议收藏,反复观看!
今天再来介绍机器学习算法的基本概念和适用场景! 首先,引用一句英国统计学家George E. P. Box的名言:All models are wrong, but some are useful. 没有哪一种算法能够适用所有情况,只有针对某一种问题更有用的算法。 也就是说&…...
SpringBoot 打包所有依赖
SpringBoot 项目打包的时候可以通过插件 spring-boot-maven-plugin 来 repackage 项目,使得打的包中包含所有依赖,可以直接运行。例如: <plugins><plugin><groupId>org.springframework.boot</groupId><artifact…...
QpushButton绘制圆角矩形并绘制背景颜色
要在QPushButton的paintEvent中绘制按钮的颜色,可以创建一个自定义的QPushButton类,并重写它的paintEvent函数。在paintEvent函数中,可以使用QPainter来绘制按钮的背景颜色。 以下是一个简单的示例代码,演示如何在自定义的QPushB…...
Core Impact 21.5 (Windows) - 高级渗透测试
Core Impact 21.5 (Windows) - 高级渗透测试 Fortra | Core Security Penetration testing software, Release Feb 2024 请访问原文链接:Core Impact 21.5 (Windows) - 高级渗透测试,查看最新版。原创作品,转载请保留出处。 作者主页&…...
【Web前端】定位_浮动_音视频
1、定位 1.1想对定位 相对定位,使用relative,参考点是标签之前的位置,不是相对于父节点、同级节点或浏览器。相对定位通过left、right进行水平偏移,通过top、bottom进行垂直偏移Ieft:表示相对于原本位置的左外边界右移的距离rig…...
【Osek网络管理测试】[TG4_TC3]LimpHome状态下的睡眠中断
🙋♂️ 【Osek网络管理测试】系列💁♂️点击跳转 文章目录 1.环境搭建2.测试目的3.测试步骤4.预期结果5.测试结果1.环境搭建 硬件:VN1630 软件:CANoe 2.测试目的 验证DUT在LimpHome状态下的睡眠中断是否正确 分析:在跛脚运行状态下,满足睡眠条件后,进入到NM…...
【QT教程】QT6硬件数据库编程 QT硬件数据库
QT6硬件数据库编程 使用AI技术辅助生成 QT界面美化视频课程 QT性能优化视频课程 QT原理与源码分析视频课程 QT QML C扩展开发视频课程 免费QT视频课程 您可以看免费1000个QT技术视频 免费QT视频课程 QT统计图和QT数据可视化视频免费看 免费QT视频课程 QT性能优化视频免费看 免…...
unaipp推荐算法的汽车租赁系统zaxzu 微信小程序hbuiderx
随着现代汽车租赁管理的快速发展,可以说汽车租赁管理已经逐渐成为现代汽车租赁管理过程中最为重要的部分之一。但是一直以来我国传统的汽车租赁管理并没有建立一套完善的行之有效的汽车租赁管理系统,传统的汽车租赁管理已经无法适应高速发展,…...
STM32单片机中C语言的一些隐藏bug
必须类型一致的判断才能正常 double a-0.4; if(a < -0.2){print("低电平"); }这段代码可能未必如你所愿的运行. < 小于号的判断一定要类型一致, 尤其是牵扯到双精度类型的判断… 一定要保证符号 两边的数据类型一致才有可能得到你想要的结果. 代码里 -0.4 默认…...
车载测试到底怎么样?真实揭秘!
什么是车载智能系统测试? 车载智能系统,是汽车智能化重要的组成部分,由旧有的车载资通讯系统结合联网汽车技术所演进而来,随着软硬件技术的不断进步, 让车载智能系统拥有强大的运算能力及多元化的应用功能。 车载智能…...
RustGUI学习(iced)之小部件(八):如何使用svg部件显示矢量图形?
前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 概述 这是本专栏的第八篇,主要讲述svg矢量图形部件的使用,会结合实…...
gitlab设置保护分支
gitlab设置保护分支方法 进入代码仓库首页,找到settings下的repository并点击进入 找到Protected Branches 下的Exoand按钮,并点击展开 可以看到已经存在默认的保护分支,通常是master/main分支,也可以添加新的保护分支 新建保护分…...
五月加仓比特币
作者:Arthur Hayes Co-Founder of 100x. 编译:Liam 编者注:本文略有删减 (以下内容仅代表作者个人观点,不应作为投资决策的依据,也不应被视为参与投资交易的建议或意见)。 从四月中旬到现在,当你…...
个人博客模板 wordpress/推广专员
1、状态更新 服务端InstanceInfo对象状态更新的流程和续约流程类似,不过该过程不再经过SpringCloud提供的InstanceRegistry类了,即SpringCloud没有再对状态更新过程进行扩展,即没有增加状态变更事件的广播。基本流程如下: Instan…...
ps海报素材网/seo网站优化知识
写一个脚本/root/bin/yesorno.sh,提示用户输入yes或no,并判断用户输入的是yes还是no,或是其它信息#!/bin/bash read -p"put your answer(yes or no):" Answer case $Answer in y|Y|[yY][eE][sS]) //判断用户输入yes时的一切可能性echo &q…...
wordpress 登陆链接/如何进入网站
缘起 随着互联网企业的不断发展,产品项目中的模块越来越多,用户体验要求也越来越高,想实现小步快跑、快速迭代的目的越来越难,还有65535,应用之间的互相调用等等问题,插件化技术应用而生。如果没有插件化技…...
做网站备案不少天/专业软文发布平台
相同点,使用drop delete truncate 都会删除表中的内容drop table 表名delete from 表名(后面不跟where语句,则也删除表中所有的数据)truncate table 表名区别首先delete 属于DML,当不commit时时不生效的而truncate 和 drop 则是直接生效的&am…...
郑州网站优化的微博_腾讯微博/微信crm系统
你希望你的网站更有说服力吗?说服的能力是演说家、作家和营销人员梦寐以求的技能。在你的网站应用一个或多个这种增强说服力的技术,可以让你游刃有余地控制转化率。 **以下是心理学中最具魅力和说服力的21种说服技巧。**有了这些技巧,就可以…...
为什么淘宝店主不自己做电商网站/百度人工
Jenkin是一个开源的CI&CD平台,提供持续集成和持续交付服务,有大量的插件来支持构建,部署,自动化等项目需求,自动化测试也可以利用Jenkins来自动构建执行,免去人工执行。 1、部署JenkinsDocker Hubhttp…...