JVM27——G1垃圾回收器的新功能
(1)字符串去重
在jdk8中,string字符串是存放在char数组中,如果通过new String的方式创建可能会导致重复创建。除了通过intern()方法来避免重复创建的发生,G1垃圾回收器会在新生代回收时并发检查是否存在重复创建的字符串,如果有则让他们指向同一个char数组。使用-XX: +UseStringDeduplication
可以开启字符串去重(默认打开)。
(2)类卸载
在jdk8u40后,所有对象在经过并发标记后,就可以知道哪些类不再被使用,当一个类加载器所有的类都不再被使用后(主要是框架、自定义类加载器),就会尝试对这些类进行类卸载。使用-XX:+ClassUnloadConcurrentWithMark
可以开启类卸载(默认开启)。
(3)巨型对象
巨型对象指大小大于region的一半的对象,在jdk8u60后,可以回收巨型对象。
巨型对象有如下特别之处。
- G1不会复制巨型对象
- 垃圾回收时优先回收
- 当某个巨型对象被老年代的incoming引用为0时,将会在新生代垃圾回收时被回收(参考下图)。
(4)动态调整阈值
并发标记必须在堆占满前完成,否则将退化为full gc(注:在新版本的jvm中,full gc已经不是前文所提到的单线程,但是仍然有很长的STW时间,需要避免)。在jdk9之前我们采用-XX:InitiatingHeapOccupancyPercent
来设置开始并发标记的阈值,但是阈值如果设置过低则频繁GC,如果设置过高则易Full GC。jdk9中可以对于阈值进行动态调整。
jdk中还有很多对于垃圾回收器的改进。建议多读官网文档:Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide, Release 16 (oracle.com)。
java全栈每日必学,不要高估自己一年能做的事,不要低估自己十年能做的事