01-013 jvm垃圾回收器G1

适用场景

1.同时注重吞吐量(throughput)和低延迟(low latency),默认暂停目标200ms;
2.超大堆内存,会将堆划分为多个大小相等的Region;
-XX:G1HeapRegionSize=size设置大小(size=1,2,4,8…)
3.整体上适用标记整理算法,两个区域之间是复制算法;
-XX:+UseG1Gc(G1启用开关,在jdk9之后是默认的)

G1垃圾回收阶段

1.Young Collection
堆划分为多个Region,可作为新生代、老年代
新生代和之前的标记整理类似
2.Young Collection + Concurrent Mark
在young GC时会进行GC Root 的初始标记
老年代占用对空间比例达到阈值时,进行并发标记(不会stw),由下面的参数决定
-XX:InitiatingHeapOccupancyPercent = percent (默认45%)
3.Mixed Collection
对E、S、O进行全面的垃圾回收
最终标记(Remark)
拷贝存活(Evacuation)
-XX:MaxGCPauseMillis = ms
在这里插入图片描述
组合为一个循环过程

full GC

新生代内存不足发生的垃圾收集 minor GC
老年代内存不足
回收速度高于产生速度,并发收集;
垃圾产生比收集快才会产生full GC

Young Collection 跨代引用

老年代引用新生代
老年代分卡表,引用新生代的为脏卡,遍历脏卡就可以,节约GC root遍历时间。
对象应用变更时会将脏卡更新指令放入一个集合,异步执行。
在这里插入图片描述

Remark

CMS 和 G1都分为两个阶段:
阶段一:并发标记阶段
阶段二:重新标记阶段
对象处理状态
黑:存活状态
灰:处理当中
白:尚未处理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
pre-write barrier + satb_mark_queue
C的引用改变前,jvm将它加入标记屏障,引用变化会执行写屏障,将C加入队列,C变成灰色,重新标记。

JDK8u20字符串去重

-XX:+UseStringDeduplication
String s1 = new String(“hello”);//char[]{‘h’,‘e’,‘l’,‘l’,‘o’}
String s2 = new String(“hello”);//char[]{‘h’,‘e’,‘l’,‘l’,‘o’}
1.将所有新分配的字符串放入一个队列;
2.当新生代回收时,G1并发检查是否有字符串重复;
3.如果它们的值一样,让它们引用同一个char[];
4.这与String,intern()不一样;
String.intern()关注的是字符串对象,字符串关注的是char[],在jvm内部,使用了不同的字符串表。
优点:节省大量内存
缺点:略微多占用了CPU时间,新生代回收时间略微增加。

JDK8u40并发标记类卸载

G1可以在所有对象都经过并发标记后,就能知道哪些类不再使用,当一个类加载器的所有类和实例都不再使用,则卸载它所加载的所有类。
参数-XX:+ClassUnloadingWithConcurrentMark默认使用

JDK8u60回收巨型对象

对象大于Region的50%,称为巨型对象;
G1不会对巨型对象进行复制;
回收时优先考虑;
G1会跟踪老年代所有incoming引用,这样老年代incoming引用为0的巨型对象就可以在新生代垃圾回收时处理掉,就是巨型对象从老年代的引用为0时,新生代垃圾回收会处理掉巨型对象。

JDK9并发标记起始时间的调整

并发标记必须在堆空间占满前完成,否则退化为full GC;回收速度跟不上产生速度,也会 full GC。
JDK9前:-XX:InitiatingHeapOccupancyPercent = percent
JDK9可以动态调整:
-XX:InitiatingHeapOccupancyPercent = percent(设置初始值);
进行数据采样并进行动态调整;
总会添加一个安全的空档空间。
避免并发垃圾回收退化为full GC 。

JDK9更高效的回收

250+增强
180+bug修复
G1(HotSpotVirtual Machine Garbage Collection Tuning Guide).

学习整理于解密JVM.

发布了53 篇原创文章 · 获赞 0 · 访问量 393

猜你喜欢

转载自blog.csdn.net/weixin_40778497/article/details/103617556