1.G1简介
G1(Gargage-First)Jdk9以后默认的垃圾回收器,取代了CMS回收器
G1是一个并行回收器,它把堆分割为很多不相关的区域(region物理上不连续),每个region大小是1~32M不等,必须是2的整数次幂。使用不同的region来表示Eden、Survivor0、Survivor1,Old等;G1每次根据允许的收集时间,优先回收价值最大的region,由于G1侧重点在于回收垃圾最大量的region,所以G1叫做gargage First
2. G1 内存模型
2.1 region
G1采用了Region的思路,将堆分割成若干大小相等的区域——region,可以通过-XX:G1HeapRegionSize设置region大小。G1仍然保留新生代老年代概念。如下图所示,一个region可能属于Eden/Survivor/Old,但一个region只能属于一个角色,空白区域代表的是未分配的内存,最后还有个特殊区域H区(Humongous),专门用于存放巨型对象,如果一个对象的大小超过region容量的50%以上,G1就会认为这个是巨型对象。
在其他垃圾回收器中,这些巨型对象会默认分配在老年代,但如果他是一个短期存活的巨型对象,放在老年代就会对垃圾回收器造成负面影响,触发老年代频繁GC,为解决这个问题,G1划分了Humongous专门存放巨型对象,如果H区装不下巨型对象那么G1会寻找连续的H区来存储,如果找不到连续的H区就不得不启动Full GC

2.2 G1收集器的回收过程
初始标记:STW,标记出从GC root直接可达对象
并发标记:与应用线程并发执行,递归追踪所有可达的对象,并发标记不会阻塞应用程序执行
最终标记:STW,为了处理并发标记过程中新产生的对象引用关系
筛选回收:与应用线程并发执行,G1 GC会根据每个Reigon垃圾堆积情况和回收价值,选择行回收部分region中垃圾对象;回收过程可能会采用复制算法和标记整理算法:复制算法--将存活对象从一个region复制到另一个reigon,并更新相关引用,标记整理算法--将涉及到对象整理和压缩以减少内存碎片
2.3 G1回收策略
YGC:新生代回收--采用复制算法,将Eden和Survior区存货对象复制到另一个Survior区或者晋升老年区,STW
Mixed GC: 新生代、老年代混合回收--标记整理算法,与应用线程并发执行,不会STW。首先会进行全局标记,然后整理,G1回收器选择回收价值高的Region对象
2.4 Remember Set
在串行和并行垃圾回收器中,GC是通过扫描整堆来确定对象是否处于可达路径中,然而G1为了避免stw的整堆扫描,为每个分区分配一个Rset(Remembered set),它内部类似一个反向指针,记录其他region对当前region的引用情况。这样带来好处是回收某个region时不需要全堆扫描,只需要扫描它的Rset就可以找到外部引用,以此来确定本分区内的对象是否存活;对于新生代Reigon的YGC会很频繁,如果每次扫描老年代对新生代的引用情况开销会很大,通过Rset的跟踪机制,可以精确知道哪些老年代引用了新生代对象,从而只扫描这些region,大大降低了YGC的扫描开销
2.5 性能优化建议
合理设置堆大小:xms和xmx设置不一样,当堆空间资源不足,会动态扩展;xms和xmx设置一样,当堆内存使用低时会浪费资源,所以开发测试环境为了解决内存资源设置xms小于xmx;但生产环境为了追求稳定,xms和xmx设置一样
调整停顿时间:调整G1的停顿时间(-XX:MaxGCPauseMillis)可以平衡垃圾回收效率和应用程序的响应时间
合理调整并行垃圾收集线程数量(2.2中第四步):通过增加并行垃圾回收线程数量(-XX:ParallesGCThreads)可以提高垃圾回收效率
监控和分析GC日志:定期监控和分析GC日志可以帮助识别潜在的内存泄漏、性能瓶颈和优化机会。可以使用JVM自带的工具(如jstat、jvisualvm)或第三方工具(如GCViewer、YourKit)来进行日志分析和性能调优。
2.6 G1核心配置参数
在JDK9及以后的版本中,G1是默认的垃圾收集器,但在JDK8中,你需要显式地启用。以下是G1收集器的一些核心配置参数:
-XX:+UseG1GC: 这个参数用于启用G1垃圾收集器。在JDK8中,你需要明确设置这个参数来使用G1,而在JDK9及更高版本中,G1是默认启用的。-XX:G1HeapRegionSize: 这个参数用于设置每个Region的大小。Region是G1收集器管理内存的基本单位。该值必须是2的幂,范围在1MB到32MB之间。G1的目标是根据最小的Java堆大小划分出约2048个这样的区域。默认情况下,这个值是堆内存的1/2000,这意味着G1收集器管理的最小堆内存应该是2GB以上,最大堆内存为64GB。-XX:MaxGCPauseMillis: 这个参数用于设置期望的最大GC停顿时间指标。G1收集器会尽力在这个时间内完成垃圾回收,以减少应用程序的停顿时间。默认值是200毫秒。-XX:ParallelGCThreads: 这个参数用于设置并行垃圾回收的线程数。这个值通常设置为与可用的CPU核心数相等,最大可以设置为8。-XX:ConcGCThreads: 这个参数用于设置并发标记的线程数。并发标记是G1收集器在垃圾回收过程中的一个阶段,这个阶段与应用程序线程并发执行。通常,这个值设置为并行垃圾回收线程数(ParallelGCThreads)的1/4左右。-XX:InitiatingHeapOccupancyPercent: 这个参数用于设置触发并发GC周期的Java堆占用率阈值。当堆内存的占用率达到这个值时,G1收集器会启动一个并发GC周期。默认值是45%,这意味着当堆内存的45%被占用时,就会触发垃圾回收。-XX:+PrintGCDetails和-verbose:gc: 这两个参数不是G1特有的,但它们对于调试和监控垃圾收集器的行为非常有用。-XX:+PrintGCDetails会打印详细的垃圾收集日志,包括每次垃圾收集的时间、回收的对象数量等信息。-verbose:gc则会启用垃圾收集的日志记录,通常与-XX:+PrintGCDetails一起使用以获取更全面的日志输出。
参考文献
https://blog.csdn.net/qq_46312987/article/details/125074757
https://blog.csdn.net/fengyuyeguirenenen/article/details/123483286?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-123483286-blog-129473473.235%5Ev38%5Epc_relevant_anti_vip&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-123483286-blog-129473473.235%5Ev38%5Epc_relevant_anti_vip&utm_relevant_index=1
浙公网安备 33010602011771号