官网:https://docs.oracle.com/en/java/javase/14/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0
zgc 简介
ZGC在java11引入,基于region内存布局,(暂时)不设分代;
使用读屏障、染色指针、内存多重映射(多个虚拟地址对应一个物理地址)等技术实现可并发的标记整理算法;
是一款低延迟的垃圾收集器,可实现对吞吐量影响不大的前提下,将任意大小堆内存的回收停顿时间控制在10ms内
*********************
内存布局
ZGC的region可以动态的创建和销毁,并且region的大小可以动态变更,主要分三类:
小型region:固定为2M,用于存储小于256KB的小对象;
中型region:固定为4M,用于存储大于等于256KB,小于4M的对象;
大型region:大小可变化,需为2M的整数倍,存储大于等于4M的对象,大型region最小为4M
*********************
内存多重映射:多个虚拟内存对应同一块物理内存
垃圾回收current reloate阶段,重分配集中region的存活对象复制到其他region中;
所有存活对象复制完成后,该region就可重新利用,有新的对象分配到该内存地址;
此时,原对象的引用关系可能仍指向该内存地址(可通过标志位与转发表找到真实的内存地址),因此形成虚拟地址与物理地址多对一的关系
染色指针
ZGC的并发整理算法通过染色指针来实现
标记信息存储在引用对象的指针上:高18位不能使用,4位用来存储标记信息,低42位存储对象地址
染色指针不支持32位平台、不支持压缩指针(-XX:+UseCompressedOops)、最多可使用4TB(2的42次方)的物理内存
*********************
标志位说明
Marked0 /Marked1:标记位,标记对象是否可用
Remapped:记录对象是否进入过重分配集(对象是否移动过)
Finalizable:标记对象是否只能通过fnalize()访问
使用两个标记位Marked0、Marked1:在不同的回收周期交替使用,上一回收周期的标志位在本周期失效,重置为0
如:一个周期中使用Marked0,存活对象标记为01,
则下一个周期使用标记位Marked1,存活对象标记为10
*********************
优势
region上的存活对象都移走后就可回收region,不用等待引用关系都修改后再释放(引用关系修改通过转发表维护);
染色指针使用读屏障修改引用关系,与使用写屏障相比,大幅减少内存屏障的使用数量;
可以开发未使用的18位记录标记、重定位等信息,将ZGC支持的堆内存由4TB拓展位128TB
zgc 回收过程
Concurrent Mark:并发标记
并发标记开始前,停止用户线程,枚举根节点;
并发标记期间,用户可以运行,根据根节点进行可达性分析并标记;
并发标记结束后,停止用户线程,做最终标记;
Concurrent Prepare for relocate:并发预重分配
扫描整个堆,找出需要清理的region,将这些region组成重分配集(relocation set);
java12开始支持的类卸载、弱引用的删除也在这个阶段完成
Conurrent relocate:并发重分配
将重分配集中的region存活对象复制到其他region中,使用转发表维护旧对象与新对象的对应关系;
region中的存活对象全部复制完成后,该region的内存空间就可重新使用;
转发表不能释放,需要等到后续阶段对象的引用关系修改完成后才能删除
Concurrent Remap:并发重映射
根据转发表,将指向旧对象指针的内存地址修改为新对象的内存地址;
这一阶段的工作不一定要立刻完成的,zgc的实现是在下一阶段的Concurrent Mark阶段修改指针的内存地址
相关参数
-XX:+UnlockExperimentalVMOptions:ZGC再java14仍处于试验阶段,需开启此参数才可使用
-XX:+UseZGC:使用zgc垃圾收集器
-XX:ConcGCThreads:使用的垃圾回收线程数,ZGC会根据当前cpu自动设置
示例
public class Test8 {
public static void main(String[] args){
byte[] b=new byte[10];
b=null;
System.gc();
}
}
*********************
虚拟机参数
-Xms20m -Xmx20m -Xlog:gc* -XX:+UnlockExperimentalVMOptions -XX:+UseZGC
*********************
控制台输出
[0.032s][info][gc,init] Initializing The Z Garbage Collector
[0.032s][info][gc,init] Version: 14+36-1461 (release)
[0.033s][info][gc,init] NUMA Support: Disabled
[0.033s][info][gc,init] CPUs: 8 total, 8 available
[0.033s][info][gc,init] Memory: 8079M
[0.033s][info][gc,init] Large Page Support: Disabled
[0.033s][info][gc,init] Medium Page Size: N/A
[0.033s][info][gc,init] Workers: 1 parallel, 1 concurrent
[0.034s][info][gc,init] Address Space Type: Contiguous/Unrestricted/Complete
[0.034s][info][gc,init] Address Space Size: 320M x 3 = 960M
[0.034s][info][gc,init] Min Capacity: 20M
[0.034s][info][gc,init] Initial Capacity: 20M
[0.034s][info][gc,init] Max Capacity: 20M
[0.034s][info][gc,init] Max Reserve: 2M
[0.034s][info][gc,init] Pre-touch: Disabled
[0.035s][info][gc,init] Uncommit: Disabled
[0.051s][info][gc,init] Runtime Workers: 1 parallel
[0.051s][info][gc ] Using The Z Garbage Collector
[0.227s][info][gc,start] GC(0) Garbage Collection (Warmup)
[0.228s][info][gc,phases] GC(0) Pause Mark Start 0.558ms
[0.233s][info][gc,phases] GC(0) Concurrent Mark 5.530ms
[0.234s][info][gc,phases] GC(0) Pause Mark End 0.084ms
[0.234s][info][gc,phases] GC(0) Concurrent Process Non-Strong References 0.589ms
[0.234s][info][gc,phases] GC(0) Concurrent Reset Relocation Set 0.001ms
[0.248s][info][gc,phases] GC(0) Concurrent Select Relocation Set 13.698ms
[0.249s][info][gc,phases] GC(0) Pause Relocate Start 0.425ms
[0.253s][info][gc,phases] GC(0) Concurrent Relocate 3.846ms
[0.253s][info][gc,load ] GC(0) Load: 0.00/0.00/0.00
[0.253s][info][gc,mmu ] GC(0) MMU: 2ms/72.1%, 5ms/88.8%, 10ms/93.6%, 20ms/96.8%, 50ms/97.9%, 100ms/98.9%
[0.253s][info][gc,marking] GC(0) Mark: 1 stripe(s), 2 proactive flush(es), 1 terminate flush(es), 1 completion(s), 0 continuation(s)
[0.253s][info][gc,reloc ] GC(0) Relocation: Successful, 1M relocated
[0.253s][info][gc,nmethod] GC(0) NMethods: 178 registered, 0 unregistered
[0.253s][info][gc,metaspace] GC(0) Metaspace: 5M used, 5M capacity, 5M committed, 8M reserved
[0.253s][info][gc,ref ] GC(0) Soft: 36 encountered, 0 discovered, 0 enqueued
[0.253s][info][gc,ref ] GC(0) Weak: 99 encountered, 92 discovered, 17 enqueued
[0.253s][info][gc,ref ] GC(0) Final: 0 encountered, 0 discovered, 0 enqueued
[0.253s][info][gc,ref ] GC(0) Phantom: 14 encountered, 14 discovered, 13 enqueued
[0.253s][info][gc,heap ] GC(0) Min Capacity: 20M(100%)
[0.253s][info][gc,heap ] GC(0) Max Capacity: 20M(100%)
[0.253s][info][gc,heap ] GC(0) Soft Max Capacity: 20M(100%)
[0.253s][info][gc,heap ] GC(0) Mark Start Mark End Relocate Start Relocate End High Low
[0.253s][info][gc,heap ] GC(0) Capacity: 20M (100%) 20M (100%) 20M (100%) 20M (100%) 20M (100%) 20M (100%)
[0.253s][info][gc,heap ] GC(0) Reserve: 2M (10%) 2M (10%) 2M (10%) 2M (10%) 2M (10%) 2M (10%)
[0.253s][info][gc,heap ] GC(0) Free: 14M (70%) 12M (60%) 12M (60%) 14M (70%) 14M (70%) 10M (50%)
[0.253s][info][gc,heap ] GC(0) Used: 4M (20%) 6M (30%) 6M (30%) 4M (20%) 8M (40%) 4M (20%)
[0.253s][info][gc,heap ] GC(0) Live: - 1M (6%) 1M (6%) 1M (6%) - -
[0.253s][info][gc,heap ] GC(0) Allocated: - 2M (10%) 2M (10%) 4M (20%) - -
[0.254s][info][gc,heap ] GC(0) Garbage: - 2M (14%) 2M (14%) 0M (4%) - -
[0.254s][info][gc,heap ] GC(0) Reclaimed: - - 0M (0%) 2M (10%) - -
[0.254s][info][gc ] GC(0) Garbage Collection (Warmup) 4M(20%)->4M(20%)
[0.294s][info][gc,start ] GC(1) Garbage Collection (System.gc())
[0.295s][info][gc,phases ] GC(1) Pause Mark Start 0.491ms
[0.302s][info][gc,phases ] GC(1) Concurrent Mark 6.725ms
[0.302s][info][gc,phases ] GC(1) Pause Mark End 0.036ms
[0.303s][info][gc,phases ] GC(1) Concurrent Process Non-Strong References 0.723ms
[0.303s][info][gc,phases ] GC(1) Concurrent Reset Relocation Set 0.003ms
[0.305s][info][gc,phases ] GC(1) Concurrent Select Relocation Set 2.693ms
[0.306s][info][gc,phases ] GC(1) Pause Relocate Start 0.347ms
[0.310s][info][gc,phases ] GC(1) Concurrent Relocate 3.839ms
[0.310s][info][gc,load ] GC(1) Load: 0.00/0.00/0.00
[0.310s][info][gc,mmu ] GC(1) MMU: 2ms/72.1%, 5ms/88.8%, 10ms/93.6%, 20ms/95.6%, 50ms/97.9%, 100ms/98.1%
[0.310s][info][gc,marking ] GC(1) Mark: 1 stripe(s), 2 proactive flush(es), 1 terminate flush(es), 0 completion(s), 0 continuation(s)
[0.310s][info][gc,reloc ] GC(1) Relocation: Successful, 1M relocated
[0.310s][info][gc,nmethod ] GC(1) NMethods: 199 registered, 0 unregistered
[0.310s][info][gc,metaspace] GC(1) Metaspace: 6M used, 6M capacity, 6M committed, 8M reserved
[0.310s][info][gc,ref ] GC(1) Soft: 40 encountered, 0 discovered, 0 enqueued
[0.310s][info][gc,ref ] GC(1) Weak: 89 encountered, 78 discovered, 1 enqueued
[0.310s][info][gc,ref ] GC(1) Final: 0 encountered, 0 discovered, 0 enqueued
[0.310s][info][gc,ref ] GC(1) Phantom: 5 encountered, 3 discovered, 0 enqueued
[0.310s][info][gc,heap ] GC(1) Min Capacity: 20M(100%)
[0.310s][info][gc,heap ] GC(1) Max Capacity: 20M(100%)
[0.310s][info][gc,heap ] GC(1) Soft Max Capacity: 20M(100%)
[0.310s][info][gc,heap ] GC(1) Mark Start Mark End Relocate Start Relocate End High Low
[0.310s][info][gc,heap ] GC(1) Capacity: 20M (100%) 20M (100%) 20M (100%) 20M (100%) 20M (100%) 20M (100%)
[0.310s][info][gc,heap ] GC(1) Reserve: 2M (10%) 2M (10%) 2M (10%) 2M (10%) 2M (10%) 2M (10%)
[0.310s][info][gc,heap ] GC(1) Free: 14M (70%) 12M (60%) 12M (60%) 14M (70%) 14M (70%) 10M (50%)
[0.310s][info][gc,heap ] GC(1) Used: 4M (20%) 6M (30%) 6M (30%) 4M (20%) 8M (40%) 4M (20%)
[0.310s][info][gc,heap ] GC(1) Live: - 1M (6%) 1M (6%) 1M (6%) - -
[0.310s][info][gc,heap ] GC(1) Allocated: - 2M (10%) 2M (10%) 4M (20%) - -
[0.310s][info][gc,heap ] GC(1) Garbage: - 2M (14%) 2M (14%) 0M (4%) - -
[0.310s][info][gc,heap ] GC(1) Reclaimed: - - 0M (0%) 2M (10%) - -
[0.310s][info][gc ] GC(1) Garbage Collection (System.gc()) 4M(20%)->4M(20%)
[0.313s][info][gc,heap,exit] Heap
[0.313s][info][gc,heap,exit] ZHeap used 4M, capacity 20M, max capacity 20M
[0.313s][info][gc,heap,exit] Metaspace used 6415K, capacity 6463K, committed 6656K, reserved 8192K