原文連接:HotSpot Virtual Machine Garbage Collection Tuning Guide,基於Java SE 14。html
本文主要包括如下內容:java
能夠將 Java HotSpot VM 垃圾收集器配置爲優先知足兩個目標之一:最大暫停時間和應用吞吐量。 若是首選目標獲得知足,收集器將嘗試最大化其餘目標。web
暫停時間是垃圾收集器中止應用程序並恢復再也不使用的空間的持續時間。 最大暫停時間目標的意圖是限制這些暫停的最長時間。算法
使用命令行選項 -XX:MaxGCPauseMillis=<nnn>
指定最大暫停時間目標。這被解釋爲向垃圾回收器提示,須要的暫停時間爲 nnn 毫秒或更短。 垃圾收集器調整 Java 堆大小和其餘與垃圾收集相關的參數,以使垃圾收集暫停時間小於 nnn 毫秒。 最大暫停時間目標的缺省值隨收集器的不一樣而變化。 這些調整可能會致使垃圾收集更頻繁地發生,從而下降應用程序的總吞吐量。 可是,在某些狀況下,暫停時間的預期目標沒法實現。bash
吞吐量目標是根據收集垃圾所花費的時間來度量的,而垃圾收集以外所花費的時間是應用程序時間。服務器
目標由命令行選項 -XX:GCTimeRatio=nnn
指定。垃圾收集時間與應用程序時間的比值爲 1/ (1+nnn)
。 例如, -XX:GCTimeRatio=19
設置了垃圾收集總時間的 1/20 或 5% 的目標。數據結構
用於垃圾收集的時間是全部垃圾收集引發的暫停的總時間。若是吞吐量目標沒有達到,那麼垃圾收集器可能採起的一個行動是增長堆的大小,以便應用程序在收集暫停之間花費的時間能夠更長。多線程
若是吞吐量和最大停頓時間目標已經達到,那麼垃圾收集器就會減小堆的大小,直到其中一個目標(老是吞吐量目標)沒法達到爲止。垃圾收集器可使用的最小和最大堆大小能夠分別使用 -Xms=<nnn>
和 -Xmx=<mmm>
來設置最小和最大堆大小。併發
一個對象被認爲是垃圾,當沒法從正在運行的程序中的任何其餘活躍對象的引用訪問到它時,VM 能夠重用它的內存。oracle
理論上,最簡單的垃圾收集算法在每次運行時遍歷每一個可達對象。任何剩下的東西都被認爲是垃圾。這種方法花費的時間與活躍對象的數量成正比,這對於維護大量活躍數據的大型應用程序來講是禁止的。
Java HotSpot 虛擬機合併了許多不一樣的垃圾收集算法,除了 ZGC 以外,這些算法都使用一種稱爲分代收集的技術。雖然簡單的垃圾收集每次都會檢查堆中的每一個活動對象,但分代收集利用了大多數應用程序的一些經驗觀察到的屬性,以最小化回收未使用(垃圾)對象所需的工做。這些被觀察到的性質中最重要的是弱世代假說,即大多數對象只能存活很短的時間。
圖3-1中的藍色區域是對象生命週期的典型分佈。X軸顯示以分配的字節爲單位的對象生存時間。Y 軸上的字節數是對象中具備相應生存期的總字節數。左邊的尖峯表示能夠回收的對象(換句話說,已經「死亡」)。 例如,迭代器對象一般只在單個循環期間保持活動。
圖3-1 對象生命週期的典型分佈
有些對象確實存活時間更長,所以分佈向右延伸。例如,一般有一些在初始化時分配的對象會一直存在直到 VM 退出。介於這兩個極端之間的是在某些中間計算期間存活的對象,這裏看到的是初始峯值右側的塊。有些應用程序具備很是不一樣的外觀分佈,但使人驚訝的是,大量應用程序具備這種通常形狀。經過關注大多數對象「早逝」這一事實,高效的收集成爲可能。
爲了對此場景進行優化,對內存進行分代管理(存放不一樣年齡段對象的內存池)。垃圾回收在每一代填滿時發生。
絕大多數對象分配在一個專門用於年輕對象的池中(年輕代) ,大多數對象死在那裏。 當年輕代的垃圾填滿時,觸發minor回收,只有年輕代的垃圾會被回收,而其餘代的垃圾則不會被回收。這種收集的成本,在第一階段,與被收集的活對象數量成正比; 年輕代回收垃圾很是快。一般,在每次minor回收期間,年輕代倖存的對象中的一部分被移動到老年代。最終,老年代將被填滿而且必須被回收,從而形成major回收,在這個回收中將收集整個堆。major回收一般比minor集合持續時間長得多,由於涉及的對象數量要大得多。圖3-2 顯示了串行垃圾收集器中代的默認安排:
圖3-2 串行收集器中各代的默認安排
在啓動時,Java HotSpot VM將整個Java堆保留在地址空間中,但除非須要,不然不爲其分配任何物理內存。覆蓋 Java 堆的整個地址空間在邏輯上被劃分爲年輕代和老年代。保留給對象存儲的完整地址空間能夠分爲年輕代和老年代。
年輕代由伊甸園(eden)和兩個倖存者(survivor)空間組成。大多數對象最初是在伊甸園中分配的。一個倖存者空間在任什麼時候候都是空的,而且在垃圾收集過程當中做爲伊甸園和另外一個倖存者空間中活動對象的目的地; 在垃圾回收以後,伊甸園和源倖存者空間都是空的。 在下一次垃圾收集中,將交換兩個倖存者空間的用途。最近填充的一個空間是將活動對象複製到其餘倖存者空間的源。對象以這種方式在倖存者空間之間複製,直到它們被複制了必定次數,或者那裏沒有足夠的空間。這些對象被複制到老年區域中。這個過程也被稱爲衰老。
垃圾收集的主要度量指標是吞吐量和延遲。
用戶對垃圾回收有不一樣的要求。
吞吐量和佔用空間最好使用特定於應用程序的指標來度量。
例如,web 服務器的吞吐量可使用一個客戶端負載生成器進行測試。 可是,經過檢查虛擬機自己的診斷輸出,很容易估計垃圾收集引發的暫停。命令行選項 -verbose:gc
打印有關堆和垃圾收集的信息。下面是一個例子:
[15,651s][info ][gc] GC(36) Pause Young (G1 Evacuation Pause) 239M->57M(307M) (15,646s, 15,651s) 5,048ms [16,162s][info ][gc] GC(37) Pause Young (G1 Evacuation Pause) 238M->57M(307M) (16,146s, 16,162s) 16,565ms [16,367s][info ][gc] GC(38) Pause Full (System.gc()) 69M->31M(104M) (16,202s, 16,367s) 164,581ms
輸出顯示了兩個年輕代的回收,接着是應用程序經過調用 System.gc()
啓動的full回收。這些行以一個時間戳開始,表示從應用程序啓動時開始的時間。 接下來是關於這一行的日誌級別(info)和標記(gc)的信息。 而後是 GC 標識號。 在本例中,有三個 gc,分別爲3六、37和38。 而後記錄 GC 的類型和聲明 GC 的緣由。 在此以後,將記錄有關內存消耗的一些信息。該日誌使用的格式:「GC以前使用的堆空間」 -> 「GC後使用的堆空間」。
示例的第一行是239M->57M(307M),這意味着在GC前使用239MB,而且GC清除了大部份內存,可是57 MB保留了下來。堆大小爲307 MB。注意,在這個示例中,full GC 將堆從307 MB 縮小到104 MB。在內存使用信息以後,記錄 GC 的開始和結束時間以及持續時間(end-start)。
-verbose:gc
命令是 -Xlog:gc
的別名。-Xlog
是 HotSpot JVM 中日誌記錄的通用日誌記錄配置選項。 這是一個基於標記的系統,其中 gc 是標記之一。要得到有關 GC 正在作什麼的更多信息,能夠配置日誌記錄,以打印包含 GC 標記和任何其餘標記的任何消息。此選項的命令行選項是-Xlog:gc*
。
下面是一個用-Xlog:gc*
記錄的 G1 年輕代回收的示例:
[10.178s][info][gc,start ] GC(36) Pause Young (G1 Evacuation Pause) [10.178s][info][gc,task ] GC(36) Using 28 workers of 28 for evacuation [10.191s][info][gc,phases ] GC(36) Pre Evacuate Collection Set: 0.0ms [10.191s][info][gc,phases ] GC(36) Evacuate Collection Set: 6.9ms [10.191s][info][gc,phases ] GC(36) Post Evacuate Collection Set: 5.9ms [10.191s][info][gc,phases ] GC(36) Other: 0.2ms [10.191s][info][gc,heap ] GC(36) Eden regions: 286->0(276) [10.191s][info][gc,heap ] GC(36) Survivor regions: 15->26(38) [10.191s][info][gc,heap ] GC(36) Old regions: 88->88 [10.191s][info][gc,heap ] GC(36) Humongous regions: 3->1 [10.191s][info][gc,metaspace ] GC(36) Metaspace: 8152K->8152K(1056768K) [10.191s][info][gc ] GC(36) Pause Young (G1 Evacuation Pause) 391M->114M(508M) 13.075ms [10.191s][info][gc,cpu ] GC(36) User=0.20s Sys=0.00s Real=0.01s
影響垃圾收集性能的兩個最重要的因素是總可用內存和專用於年輕代的堆的比例。
影響垃圾收集性能的最重要因素是總可用內存。 因爲收集發生在代填滿時,所以吞吐量與可用內存量成反比。
許多選項影響代大小。圖4-1說明了堆中提交的空間和虛擬空間之間的區別。在初始化虛擬機時,將保留堆的整個空間。可使用 -Xmx
選項指定保留空間的大小。 若是 -Xms
參數的值小於 -Xmx
參數的值,那麼並不是全部保留的空間都當即提交給虛擬機。未提交的空間在這個圖中被標記爲「virtual」。堆的不一樣部分,即老年代和年輕代,能夠根據須要增加到虛擬空間的極限。
其中一些參數是堆的一部分與另外一部分的比率。例如,參數 –XX:NewRatio
表示老年代與年輕代的相對大小。
圖4-1 堆選項
默認狀況下,虛擬機在每次回收中增長或縮小堆,以便將每次回收中的可用空間與活動對象的比例保持在特定範圍內。
此目標範圍由選項 -XX:MinHeapFreeRatio=<minimum>
和 -XX:MaxHeapFreeRatio=<maximum>
設置爲百分比,總大小限制在 –Xms<min>
和 –Xmx<max>
之間。
使用這些選項,若是一代中的可用空間比例低於40% ,那麼這一代將擴展到保持40% 的可用空間,直到這一代的最大容許空間大小。相似地,若是可用空間超過70% ,那麼這一代就會收縮,以便只有70% 的空間是可用的,這取決於這一代的最小大小。
Java SE 中用於並行收集器的計算如今用於全部的垃圾收集器。計算的一部分是64位平臺的最大堆大小的上限。對於客戶端JVM也有相似的計算,這會致使堆的最大空間小於服務器JVM。
如下是關於服務器應用程序堆大小的通常準則:
-Xms
和 -Xmx
設置爲相同的值能夠從虛擬機中刪除最重要的大小調整決策,從而提升可預測性。可是,若是你作了一個糟糕的選擇,那麼虛擬機就沒法進行補償。若是你須要最小化應用程序的動態內存佔用(執行過程當中消耗的最大 RAM) ,那麼能夠經過最小化 Java 堆大小來實現這一點。
使用命令行選項-XX:MaxHeapFreeRatio
(默認值爲70%) 和 -XX:MinHeapFreeRatio
(默認值爲40%)下降相關比例,從而最小化 Java 堆大小。
除了總的可用內存以外,影響垃圾收集性能的第二個最重要的因素是專用於年輕代的堆的比例。
默認狀況下,年輕代的大小由選項 -XX:NewRatio
控制。
例如,設置 -XX:NewRatio=3
意味着年輕代和老年代之間的比例爲1:3。 換句話說,伊甸園 和 倖存者空間的總和將是堆總大小的四分之一。
選項 -XX:NewSize
和 -XX:MaxNewSize
設置了年輕代的下限和上限。 將這些值設置爲相同的值能夠固定年輕代,就像將 -Xms
和 -Xmx
設置爲相同的值能夠固定堆總大小同樣。這有助於以比 -XX:NewRatio
所容許的整數倍更細的粒度調優年輕代。
你可使用選項 -XX:SurvivorRatio
來調整倖存者空間的大小,但這一般對性能並不重要。
例如, -XX:SurvivorRatio=6
將伊甸園和倖存者空間之間的比率設置爲1:6。 換句話說,每一個倖存者的空間是伊甸園的1/6,也就是年輕代的1/8(不是1/7,由於存在兩個倖存者的空間)。
若是倖存者空間過小,那麼複製收集將直接溢出到老年代中。若是倖存者空間太大,那麼它們就是無用的空。在每次垃圾收集時,虛擬機都會選擇一個閾值數字,這是一個對象在老化以前能夠複製的次數。選擇這個門檻是爲了讓倖存者保持半滿狀態。 你可使用日誌配置 -Xlog:gc
,age可用於顯示此閾值以及新生成的對象的年齡。這對於觀察應用程序的生命週期分佈也頗有用。
表4-1 提供了倖存者空間大小的默認值。
選項 | 默認值 |
---|---|
-XX:NewRatio | 2 |
-XX:NewSize | 1310 MB |
-XX:MaxNewSize | not limited |
-XX:SurvivorRatio | 8 |
年輕代的最大空間是根據總堆的最大空間和 -XX:NewRatio
參數的值計算出來的。-XX:MaxNewSize
參數的默認值"not limited" 意味着計算值不受 -XX:MaxNewSize
的限制,除非在命令行上指定了 -XX:MaxNewSize
的值。
Java HotSpot虛擬機包含3種不一樣類型的收集器,每種收集器具備不一樣的性能特徵。
串行收集器使用單個線程執行全部垃圾收集工做,這使得它相對高效,由於線程之間沒有通訊開銷。
它最適合於單處理器機器,由於它不能利用多處理器硬件,儘管它能夠在多處理器上用於具備小數據集(大約100MB)的應用程序。在某些硬件和操做系統配置上,串行收集器是默認選擇的,或者可使用選項 -XX:+UseSerialGC
顯式啓用串行收集器。
並行收集器也稱爲吞吐量收集器,它是一個相似於串行收集器的分代收集器。 串行和並行收集器之間的主要區別是,並行收集器有多個線程,用於加速垃圾收集。
並行收集器用於在多處理器或多線程硬件上運行的具備中等到大型數據集的應用程序。 您可使用 -XX:+UseParallelGC
選項啓用它。
並行壓縮是使並行收集器可以並行執行major回收的一個特性。若是不進行並行壓縮,major回收將使用單個線程執行,這將極大地限制可伸縮性。若是指定了 -XX:+UseParallelGC
選項,則默認狀況下啓用並行壓縮。 您可使用 -XX:-UseParallelOldGC
選項禁用它。
G1主要是一個併發收集器。大多數併發收集器併發執行一些代價高昂的工做到應用程序。 此收集器設計用於從小型機器擴展到大型具備大量內存的多處理器機器。 它提供了以高几率知足停頓時間目標的能力,同時實現高吞吐量。
在大多數硬件和操做系統配置中,默認選擇 G1,或者可使用 -XX:+UseG1GC
顯式啓用 G1。
Z垃圾收集器(ZGC)是一個可伸縮的低延遲垃圾收集器。ZGC併發地執行全部昂貴的工做,而不中止應用程序線程的執行。
ZGC 適用於須要低延遲(少於10毫秒的暫停) 或 使用很是大的堆(TB級)的應用程序。 能夠經過使用 -XX:+UseZGC
選項啓用。
ZGC是一個實驗性的特性,從 JDK 11開始。
若是須要,調整堆大小以提升性能。若是性能仍然不能達到你的目標,那麼使用下面的準則做爲選擇收集器的起點:
-XX:+UseSerialGC
選擇串行收集器。-XX:+UseSerialGC
選擇串行收集器。-XX:+UseParallelGC
選擇並行收集器。-XX:+UseG1GC
。-XX:UseZGC
。這些準則只是選擇收集器的起點,由於性能取決於堆的大小、應用程序維護的實時數據量以及可用處理器的數量和速度。
若是推薦的收集器沒有達到預期的性能,那麼首先嚐試調整堆和分代大小,以知足預期的目標。 若是性能仍然不足,那麼嘗試另外一個收集器: 使用併發收集器來減小暫停時間,並使用並行收集器來增長多處理器硬件上的總吞吐量。
小結:
並行收集器(也稱爲吞吐量收集器)是相似於串行收集器的分代收集器。 串行和並行收集器之間的主要區別是,並行收集器有多個線程,用於加速垃圾回收。
經過命令行選項 -XX:+UseParallelGC
啓用並行收集器。 默認狀況下,使用此選項,次要(minor)和主要(major)回收都將並行運行,以進一步減小垃圾回收開銷。
可使用命令行選項 -XX:ParallelGCThreads=<N>
控制垃圾收集器線程的數量。
在並行收集器中,各代的排列方式是不一樣的。
圖6-1 並行收集器中各代的排列
當使用 -XX:+UseParallelGC
選擇並行收集器時,它支持自動調優方法,容許您指定行爲,而不是分代大小和其餘低級調優細節。
最大垃圾收集暫停時間: 使用命令行選項 -XX:MaxGCPauseMillis=<N>
指定最大暫停時間目標。這被解釋爲須要
吞吐量: 吞吐量目標是根據執行垃圾回收所花費的時間與垃圾回收以外所花費的時間(稱爲應用程序時間)來度量的。目標由命令行選項 -XX:GCTimeRatio=<N>
指定,該選項將垃圾收集時間與應用程序時間的比率設置爲1 / (1 +
例如, -XX:GCTimeRatio=19
設置了垃圾收集佔總時間的1/20或5%的目標。 默認值爲99,結果是垃圾回收時間的目標爲1%。
內存空間: 使用選項 -Xmx<N>
指定最大堆內存佔用。此外,收集器還有一個隱式目標,即在知足其餘目標的狀況下最小化堆的大小。
目標是最大暫停時間目標、吞吐量目標和最小佔用空間目標,目標按照這個順序實現:
首先實現最大暫停時間目標。只有在知足了這個要求以後,吞吐量目標才能實現。 一樣,只有在前兩個目標已經實現以後,纔會考慮內存大小目標。
除非在命令行中指定了初始堆大小和最大堆大小,不然將根據計算機上的內存量計算它們。默認的最大堆大小是物理內存的1/4,而初始堆大小是物理內存的1/64。 分配給年輕代的最大空間是總堆大小的1/3。
你可使用選項 -Xms
和 -Xmx
指定初始堆大小和最大堆大小。
若是您知道應用程序須要多少堆才能正常工做,那麼能夠將 -Xms
和 -Xmx
設置爲相同的值。若是您不知道,那麼 JVM 將開始使用初始堆大小,而後增長 Java 堆,直到找到堆使用量和性能之間的平衡。
其餘參數和選項可能會影響這些默認值。要驗證默認值,請使用 -XX:+PrintFlagsFinal
選項並在輸出中查找 -XX:MaxHeapSize
。 例如,在 Linux 上你能夠運行如下命令:
java -XX:+PrintFlagsFinal <GC options> -version | grep MaxHeapSize
若是在垃圾回收(GC)上花費了太多時間,並行收集器將拋出 OutOfMemoryError 錯誤。
若是超過98% 的總時間用於垃圾回收,而回收的堆不到2%,則拋出 OutOfMemoryError
。此特性旨在防止應用程序在較長時間內運行,同時因爲堆過小而幾乎或根本沒有進展。若是須要,能夠經過向命令行添加選項 -XX:-UseGCOverheadLimit
來禁用此特性。
G1垃圾收集器的目標是將多處理器機器擴展到大量內存。它試圖以較高的機率知足垃圾收集暫停時間目標,同時實現較高的吞吐量而不須要進行配置。G1的目標是使用當前的目標應用程序和環境,在延遲和吞吐量之間提供最佳的平衡。
與吞吐量收集器相比,雖然G1收集器的垃圾收集暫停時間一般要短得多,但應用程序吞吐量也每每略低。
G1是默認收集器。
G1垃圾回收器是默認回收器,所以一般不須要執行任何其餘操做。您能夠經過在命令行上提供 -XX:+UseG1GC
來顯式啓用它。
G1是一個分代的、遞增的、並行的、大部分併發的、stop-the-world和疏散垃圾收集器,它監視每一個stop-the-world暫停的時間目標。與其餘收集器相似,G1將堆分爲(虛擬的)年輕代和老年代。空間回收的努力集中在年輕代身上,這樣作效率最高,偶爾的空間回收在老年代中。
有些操做老是在stop-the-world暫停中執行,以提升吞吐量。應用程序中止的其餘操做會花費更多時間,好比全局標記之類的整堆操做會與應用程序並行執行。 爲了使stop-the-world在空間回收方面的停頓時間縮短,G1逐步並行地進行空間回收。 G1經過跟蹤之前應用程序行爲的信息和垃圾收集暫停來構建相關成本的模型,從而實現可預測性。它利用這個信息來計算停頓時所作的工做量。例如,G1首先在效率最高的區域回收空間(這些區域大部分都是垃圾,所以取名爲 G1)。
G1主要經過撤離來回收空間: 在選定的內存區域內找到的活動對象被複制到新的內存區域,並在處理過程當中對其進行壓縮。在完成疏散以後,之前被活動對象佔用的空間將被應用程序重用以進行分配。
G1收集器不是實時收集器。它試圖在更長的時間內以高几率實現設定的暫停時間目標,但在給定的暫停時間內並不老是絕對肯定。
G1將堆劃分爲一組大小相同的堆區域,每一個區域都有一個連續的虛擬內存範圍,如圖7-1所示。區域是內存分配和內存回收的單位。在任何給定的時間,這些區域中的每個均可以是空的(淺灰色) ,或者分配給特定的一代,年輕的或老年的。當內存請求進入時,內存管理器分配空閒區域。內存管理器將它們分配給一個代,而後將它們做爲可用空間返回給應用程序,應用程序能夠將其分配給本身。
圖7-1 G1垃圾收集器堆佈局
年輕代包含伊甸園區域(紅色)和倖存者區域(紅色帶有"S")。這些區域提供了與其餘收集器中的相應連續空間相同的功能,不一樣之處在於,在G1中,這些區域一般以非連續的模式佈局在內存中。老區域(淺藍色)組成了老年代。對於跨越多個區域的對象,老年代區域可能很是巨大(淺藍色帶"H")。
應用程序老是分配給年輕代,即伊甸園區域,但直接分配給老年代的大型對象除外。
在較高的水平上,G1收集器在兩個階段之間交替。只有年輕(young-only)階段包含垃圾回收,這些垃圾回收會逐漸用老年代中的對象填充當前可用的內存。在空間回收階段,除了處理年輕代的問題外,G1逐步收回老年代的空間。而後循環從新開始,只有年輕的階段。
Figure 9-2 gives an overview about this cycle with an example of the sequence of garbage collection pauses that could occur:
圖7-2給出了這個循環的概述,並舉例說明了可能發生的垃圾收集暫停的順序:
圖7-2 垃圾收集週期概覽
下面的列表詳細描述了G1垃圾收集週期的各個階段,它們之間的停頓和過渡:
在空間回收以後,收集週期從另外一個young-only的階段從新開始。做爲備份,若是應用程序在收集存活信息時耗盡了內存,G1會像其餘收集器同樣執行就地stop-the-world的徹底堆壓縮(Full GC)。
G1在調整Java堆大小時遵循標準規則,使用 -XX:InitialHeapSize
做爲最小的 Java 堆空間, -XX:MaxHeapSize
做爲最大的 Java 堆空間, -XX:MinHeapFreeRatio
做爲最小的可用內存百分比, -XX:MaxHeapFreeRatio
用於肯定調整大小後可用內存的最大百分比。 G1收集器僅在執行重標記(Remark) 和 Full GC 暫停期間考慮調整 Java 堆的大小。 這個過程能夠從操做系統釋放內存或分配內存。
G1老是在下一個突變子階段的正常年輕代回收結束時測量年輕代的大小。經過這種方式,G1能夠知足使用 -XX:MaxGCPauseTimeMillis
和 -XX:PauseTimeIntervalMillis
設置的暫停時間目標,該目標基於對實際暫停時間的長期觀察。它考慮到了一樣規模的年輕代須要多長時間才能刪除。這包括在回收過程當中須要複製多少對象以及這些對象之間的互聯程度等信息。
若是沒有其餘限制,那麼 G1能夠在 -XX:G1NewSizePercent
和 -XX:G1MaxNewSizePercent
肯定的值之間自適應地調全年輕代大小,以知足暫停時間的要求。
或者,可使用 -XX:NewSize
和 -XX:MaxNewSize
分別設置年輕代的最小值和最大值。
注意: 只指定後面這些選項中的一個,就能夠將年輕代大小精確地固定爲分別使用 -XX:NewSize
和 -XX:MaxNewSize
傳遞的值。這將禁用暫停時間控制。
在空間回收階段,G1試圖在一次垃圾回收暫停中最大化在老年代中回收的空間量。 年輕年代的大小設置爲容許的最小值,一般由 -XX:G1NewSizePercent
肯定。
若是因爲應用程序不活躍而致使長時間沒有垃圾收集,那麼虛擬機可能會長時間保留大量未使用的內存,這些內存能夠在其餘地方使用。爲了不這種狀況,能夠強制 G1使用 -XX:G1PeriodicGCInterval
選項執行常規垃圾收集。此選項肯定 G1考慮執行垃圾回收的最小間隔(毫秒)。若是自之前任何垃圾收集暫停以來已通過去了這段時間,而且沒有正在進行的併發循環,G1將觸發額外的垃圾回收。
啓動堆佔用百分比(Initiating Heap Occupancy Percent, IHOP)是觸發初始標記回收的閾值,它被定義爲老年代大小的百分比。
默認狀況下,G1經過在標記週期中觀察標記須要多長時間以及在老年代中一般分配多少內存來自動肯定最佳IHOP。這個特性稱爲自適應IHOP。若是這個特性是活動的,那麼選項 -XX:InitiatingHeapOccupancyPercent
肯定初始值做爲當前老年代代大小的百分比,只要沒有足夠的觀測值來很好地預測啓動堆佔用閾值。 使用 -XX:-G1UseAdaptiveIHOP
選項關閉 G1的此行爲。 在這種狀況下, -XX:InitiatingHeapOccupancyPercent
的值老是決定這個閾值。
G1標記使用一種稱爲「初始快照」(Snapshot-At-The-Beginning,SATB)的算法。 它在初始標記暫停時拍攝堆的虛擬快照,此時全部在標記開始時處於活動狀態的對象都被認爲在標記的剩餘時間處於活動狀態。這意味着,爲了空間回收的目的(除了一些例外) ,在標記期間變爲死的(不可到達的)對象仍然被認爲是活的。與其餘收集器相比,這可能會致使一些額外的內存被錯誤地保留。可是,SATB 可能在Remark暫停期間提供更好的延遲。在這個標記期間過於保守地考慮活動對象將在下一個標記期間被回收。
選項和默認值
|
描述 |
---|---|
-XX:MaxGCPauseMillis=200 | 最大暫停時間的目標 |
-XX:GCPauseTimeInterval=
|
最大暫停時間間隔的目標。 默認狀況下,G1不設置任何目標,容許 G1在極端狀況下背靠背地執行垃圾收集。 |
-XX:ParallelGCThreads=
|
垃圾回收暫停期間用於並行工做的最大線程數。 這是根據虛擬機如下列方式運行的計算機的可用線程數得出的: 若是進程可用的 CPU 線程數少於或等於8,則使用該線程。不然,使用線程數的5/8。 |
-XX:ConcGCThreads=
|
|
-XX:+G1UseAdaptiveIHOP -XX:InitiatingHeapOccupancyPercent=45 |
|
-XX:G1HeapRegionSize=
|
|
-XX:G1NewSizePercent=5 -XX:G1MaxNewSizePercent=60 |
|
-XX:G1HeapWastePercent=5 | |
-XX:G1MixedGCCountTarget=8 | |
-XX:G1MixedGCLiveThresholdPercent=85 |
這是G1與其餘收集器之間主要區別的摘要:
因爲它的工做原理,G1有一些獨特的機制來提升垃圾回收效率:
從老年代回收空的大型對象始終處於啓用狀態。您可使用 -XX:-G1EagerReclaimHumongousObjects
選項禁用此功能。 默認狀況下禁用字符串重複數據刪除。 您可使用選項 -XX:+G1EnableStringDeduplication
啓用它。
Z垃圾收集器(ZGC)是一個可伸縮的低延遲垃圾收集器。ZGC併發地執行全部昂貴的工做,而不須要中止應用程序線程的執行超過10ms,這使得它適合於須要低延遲或使用很是大的堆(TB級)的應用程序。
Z垃圾收集器是一個實驗性特性,能夠經過命令行選項 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC
啓用。
ZGC最重要的調優選項是設置最大堆大小(-Xmx
)。
可能須要考慮的第二個調優選項是設置併發GC線程的數量(-XX:ConcGCThreads
)。
應用程序與垃圾回收交互的另外一種方式是使用 System.gc()
顯式調用full垃圾回收。
Java類在 Java Hotspot虛擬機中有一個內部表示,稱爲類元數據。
在Java Hotspot虛擬機的之前版本中,類元數據是在所謂的永久代(permanent generation)中分配的。從JDK 8開始,永久代被刪除,類元數據在本機內存中(native memory)分配。默認狀況下,可用於類元數據的本機內存量是無限的。使用選項 -XX:MaxMetaspaceSize
對用於類元數據的本機內存量設置上限。