JVM 垃圾回收(三)垃圾回收器和 JDK版本更新有关垃圾回收机制内容
1. 串行
特点:
- 单线程
- 堆内存较小,适合个人电脑
2. 吞吐量优先
让单位时间内, STW的时间最短0.2 0.2 = 0.4 ,垃圾回收时间占比最低,这样就称吞吐量高。当进行垃圾回收的时候cpu占用会升高。
3. 响应时间优先
特点
- 多线程
- 堆内存较大,多核 cpu
- 尽可能让单次 STW 的时间最短 0.1 0.1 0.1 0.1 0.1 = 0.5
4. G1 (Garbage One)
定义: Garbage First
发展:
- 2004 论文发布
- 2009 JDK 6u14 体验
- 2012 JDK 7u4 官方支持
- 2017 JDK 9 默认 标志CMS算法被代替
适用场景
- 同时注重吞吐量(Throughput)和低延迟(Low latency),默认的暂停目标是 200 ms
- 超大堆内存,会将堆划分为多个大小相等的 Region
- 整体上是 标记+整理 算法,两个区域之间是 复制 算法
相关JVM参数
- -XX:+UseG1GC 启动G1,jdk9及以上版本为默认
- -XX:G1HeapRegionSize=size
- -XX:MaxGCPauseMillis=time
G1垃圾回收器的阶段
- 新生代垃圾回收
新生代->垃圾回收-> 晋升老年代 - 新生代垃圾回收+并发标记
在 Young GC 时会进行 GC Root 的初始标记
老年代占用堆空间比例达到阈值时,进行并发标记(不会 STW),由下面的 JVM 参数决定 -XX:InitiatingHeap0ccupancyPercent=percent (默认45%) - 混合收集(优先回收垃圾最多的区域)
对伊甸园区、新生代、老年代的垃圾进行回收,最终标记(Remark)会 STW
拷贝存活(Evacuation)会 STW,G1会根据停止时间进行选择性(价值最高)的进行垃圾回收。使用参数 -XX:MaxGCPauseMillis=ms
5.minor GC 和 Full GC的区别
- SerialGC
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足发生的垃圾收集 - full gc - ParallelGC
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足发生的垃圾收集 - full gc - CMS
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足 - G1
新生代内存不足发生的垃圾收集 - minor gc
老年代内存不足
6. JDK 8u20 字符串去重
优点:节省大量内存
缺点:略微多占用了 cpu 时间,新生代回收时间略微增加
使用一个JVM参数 : -XX:+UseStringDeduplication
实现逻辑:将所有新分配的字符串放入一个队列,当新生代回收时,G1并发检查是否有字符串重复,如果它们值一样,让它们引用同一个 char []
7. JDK 8u40 并发标记类卸载
所有对象都经过并发标记后,就能知道哪些类不再被使用,当一个类加载器的所有类都不再使用,则卸载它所加载的所有类 -XX:+ClassUnloadingWithConcurrentMark 默认启用
8. JDK 8u60 回收巨型对象
一个对象大于 region 的一半时,称之为巨型对象
- G1 不会对巨型对象进行拷贝
- 回收时被优先考虑
- G1 会跟踪老年代所有 incoming 引用,这样老年代 incoming 引用为0 的巨型对象就可以在新生代垃圾回收时处理掉
9. JDK 9 并发标记起始时间的调整
- 并发标记必须在堆空间占满前完成,否则退化为 FullGC
- JDK 9 之前需要使用 -XX:InitiatingHeapOccupancyPercent
- JDK 9 可以动态调整
- -XX:InitiatingHeapOccupancyPercent 用来设置初始值
- 进行数据采样并动态调整
- 总会添加一个安全的空档空间