ZGC是從JDK11中引入的一種新的支持彈性伸縮和低延遲垃圾收集器,ZGC可以工作在KB~TB的內(nèi)存之下冷溃,作為一種并發(fā)的垃圾收集器,ZGC保證應(yīng)用延遲不會超過10毫秒(即便在堆內(nèi)存很大的情況下)梦裂,在JDK11中是以實驗階段的特性被發(fā)布出來的似枕,到JDK13時,ZGC可以支持到16TB的堆內(nèi)存年柠,并且可以將未提交的內(nèi)存歸還給操作系統(tǒng)凿歼。
為什么引入ZGC
JVM的自動垃圾收集雖然減少了開發(fā)人員的工作,在一定程度上減少了內(nèi)存泄漏的風(fēng)險冗恨,但是由于GC是自動進行的答憔,一些無法預(yù)知的事情有時候可能產(chǎn)生對應(yīng)用有害的影響。
- 延遲增加導(dǎo)致應(yīng)用的吞吐量和性能
隨著時代發(fā)展掀抹,硬件會逐漸便宜虐拓,應(yīng)用使用的內(nèi)存將會越來越大,但是又不能增加延遲渴丸,降低吞吐量
ZGC保證侯嘀,不管在什么情況下另凌,延遲不會超過10毫秒。
The Z Garbage Collector, also known as ZGC, is a scalable low latency garbage collector designed to meet the following goals:
- Pause times do not exceed 10ms
- Pause times do not increase with the heap or live-set size
- Handle heaps ranging from a few hundred megabytes to multi terabytes in size
ZGC特性
ZGC最典型的特性是它是一款并發(fā)(concurrent)的GC戒幔,其它的特性如下:
- 它可以標(biāo)記內(nèi)存吠谢,復(fù)制和遷移(relocate)內(nèi)存,所有的操作都是并發(fā)的诗茎,同時它有一個并發(fā)的引用處理器
- 其它的垃圾收集器都是使用
store barriers
工坊,ZGC使用load barriers
,用于跟蹤內(nèi)存- lock->unlock->read->load 讀內(nèi)存
- use->assign->store->write 寫內(nèi)存
- ZGC可以更加靈活的配置大小和策略敢订,相比于G1王污,它可以更好的處理非常大(very large)對象的釋放
- ZGC只有一代,沒有新生代楚午,老年代什么的昭齐,但是ZGC可以支持局部壓縮,在內(nèi)存恢復(fù)和遷移(reclaim and relocate)時矾柜,ZGC仍然有很高的性能
- ZGC依賴NUMA-aware(非均衡存儲器訪問)阱驾,需要我們的內(nèi)存支持這種特點
特性進度表
- JDK11,2018年 9月
- ZGC發(fā)布
- 不支持類的卸載怪蔑。-XX:+ClassUnloading 不生效
- JDK12 2019年 3月
- 支持并發(fā)的類卸載
- 暫停時間進一步縮短
- JDK13 2019年 9月
- 最大堆內(nèi)存從4TB -> 16TB
- 支持歸還未使用的內(nèi)存 uncommitting unused memory
- 支持Linux與/AArch64平臺
- 減少時間到一個固定的時間點之下 (Reduced Time-To-Safepoint)
- 支持 -XX:SoftMaxHeapSize 里覆,當(dāng)設(shè)置這個參數(shù)的時候,ZGC會盡量在指定的內(nèi)存大小之下缆瓣,除非為了避免內(nèi)存溢出:參考:https://bugs.openjdk.java.net/browse/JDK-8222487
- JDK 14 計劃在2020年3月
- 增加穩(wěn)定性
- 支持不連續(xù)的地址空間
- ...
ZGC支持的平臺:
平臺 | 是否支持 | 當(dāng)前進度 |
---|---|---|
Linux/x64 | Y | Since JDK 11 |
Linux/AArch64 | Y | Since JDK 13 |
macOS | In Progress | |
Windows | In Progress |
垃圾收集原理
幾個術(shù)語:
- parallel 多個垃圾收集線程在一起工作喧枷,應(yīng)用可能會停止
- serial 垃圾收集器只有一個線程在工作
- stop the world 應(yīng)用程序停止
- concurrent 垃圾收集器在后臺運行,應(yīng)用程序同時也在運行
- incremental 在垃圾收集工作結(jié)束之前弓坞,先停止垃圾收集隧甚,等一會再過來完成剩下的工作
ZGC引入了兩個新的概念,pointer coloring和load barriers.
Point Coloring
這個特性讓ZGC能夠發(fā)現(xiàn)昼丑,標(biāo)記呻逆,定位和重新映射對象夸赫,它只能工作在64位的操作系統(tǒng)上菩帝,實現(xiàn)colored pointer需要虛擬地址(virtual address masking)。
- finalizable 對象可以被finalizer到達
- marked0 和marked1 標(biāo)記可達的對象
- remap 引用指針到當(dāng)前對象的地址茬腿,對象可能會被relocate呼奢,這個地址表示對象被relocate
Load Barrier
load barrier是一段代碼,當(dāng)線程從堆中加載引用的時候被運行切平。例如握础,當(dāng)我們訪問對象的一個非主要類型的屬性。
在ZGC中悴品,load barrier檢查引用的元數(shù)據(jù)位禀综,根據(jù)元數(shù)據(jù)位對引用的對象做一些處理简烘,因此可能在我們獲取對象的時候?qū)ο蟮囊脮恍薷牡簦遣挥绊懳覀兊氖褂谩?/p>
實戰(zhàn)
可以從jdk官網(wǎng)下載最新版本的JDK定枷,下載地址:
https://www.oracle.com/technetwork/java/javase/downloads/jdk13-downloads-5672538.html
快速開始
GC日志標(biāo)記格式如下:
-Xlog:<tag set>,[<tag set>, ...]:<log file>
只是想要查看ZGC是否生效:
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xlog:gc
想要查看更加詳細(xì)的ZGC日志信息:
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xlog:gc*
將更詳細(xì)的日志信息記錄在文件中:
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xlog:gc*:gc.log
GC調(diào)參
通用GC選項 | ZGC選項 | ZGC 診斷選項-XX:+UnlockDiagnosticVMOptions |
---|---|---|
-XX:MinHeapSize, -Xms -XX:InitialHeapSize, -Xms -XX:MaxHeapSize, -Xmx -XX:SoftMaxHeapSize -XX:SoftRefLRUPolicyMSPerMB | -XX:ZAllocationSpikeTolerance -XX:ZCollectionInterval -XX:ZFragmentationLimit -XX:ZMarkStackSpaceLimit -XX:ZPath -XX:ZUncommit -XX:ZUncommitDelay | -XX:ZProactive -XX:ZStatisticsInterval -XX:ZVerifyForwarding -XX:ZVerifyMarking -XX:ZVerifyObjects -XX:ZVerifyRoots -XX:ZVerifyViews |
是否啟用NUMA支持:
# 啟用NUMA
-XX:+UseNUMA
# 停用NUMA
-XX:-UseNUMA
調(diào)整并發(fā)的線程數(shù):
-XX:ConcGCThreads=
返回未提交的內(nèi)存到操作系統(tǒng)孤澎,堆內(nèi)存不會地址設(shè)置的最小堆內(nèi)存-Xms
# 多久未提交的內(nèi)存會返回給系統(tǒng)
-XX:+ZUncommit -XX:ZUncommitDelay=<seconds>
開啟大分頁,一般會帶來更好的性能提升欠窒,吞吐量覆旭,延遲和啟動時間都有所改善。并沒有看到明顯的缺點
- 大分頁在Linux系統(tǒng)中一般為2MB的大小岖妄,如果有16G的堆內(nèi)存型将,那么意味著需要16GB/2MB = 8192個大分頁,以下命令需要 Linux kernel >= 4.14
# 配置操作系統(tǒng)中的分頁池數(shù)量
echo 9216 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 查看系統(tǒng)中現(xiàn)在的分頁數(shù)量
cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
-XX:+UseLargePages
- 如果Linux kernel < 4.14荐虐,那么如下方式
mkdir /hugepages
mount -t hugetlbfs -o uid=123 nodev /hugepages
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xms16G -Xmx16G -XX:+UseLargePages
開啟透明分頁七兜,透明分頁可能導(dǎo)致延遲上的一些問題,有時候不推薦使用福扬,開啟透明分頁需要Linux kernel < 4.7
# 開啟透明分頁
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
echo advise > /sys/kernel/mm/transparent_hugepage/shmem_enabled
-XX:+UseTransparentHugePage
最后
ZGC仍然是處于試驗特性階段惊搏,但其保證延遲時間不低于10ms的特性,以及當(dāng)前對堆內(nèi)存大小的支持力度忧换,還是值得一試恬惯,讓我們期待ZGC成為一款更加優(yōu)越的垃圾收集器吧。