JVM G1垃圾回收器的优化 (JDK8-JDK9)
1.字符串去重(JDK8u20 )
-XX:+UseStringDeduplication //设定开关
JDK中字符串底层是char数组,当频繁创建相同的字符串对象,会:
-
将所有新分配的字符串放入一个队列,
-
在新生代垃圾回收时,检查新创建字符串队列中是否有字符串重复
-
如果它们值一样,会让重复字符串对象引用相同的队列中char数组
-
注意,与String.intern()不一样:
-
在JVM内部,使用了不同的字符串表
2.并发标记类卸载(JDK8u40)
所有对象经过并发标记后,就能知道哪些类不再被使用,当一个类加载器的所有类都不再被使用,则卸载它所加载的所有类
-XX:+ClassUnloadingWithConcurrentMark //默认启动
3.回收巨型对象
-
一个对象大于region的一半时,成为巨型对象
-
G1不会对巨型对象进行拷贝
-
回收时会优先被考虑
-
G1会跟踪老年代所有incoming引用,这样老年代incoming引用为0的巨型对象就可以在新生代垃圾回收时处理掉
4并发标记起始时间的调整(JDK9)
-
目的:避免fullgc
-
fullgc问题:垃圾回收速度跟不上垃圾产生速度。stw时间更长,应该尽可能避免fullgc。
-
手段:提前让垃圾回收开始(并发标记、混合回收)。
-
JDK9之前要设置参数:
-XX:InitiatingHeapOccupyPercent //阈值默认45%
JDK可以动态调整:
-XX:InitiatingHeapOccupyPercent //JDK9之后此参数仅仅用来设置初始值
-
进行数据采样并动态调整
-
总之会添加一个安全的空挡空间