1,jvm常用參數
可以通過java -XX:+PrintFlagsFinal
命令查看jvm各參數在當前機器上的默認值,
或者jinfo -flag MetaspaceSize pid
查看指定進程的參數的值:
參數 | 功能 | 默認值 |
---|---|---|
-Xms | 初始堆大小 | 物理內存1/64 |
-Xmx | 最大堆大小 | 物理內存1/4 |
-Xmn | 年輕代大小 (NewSize與MaxNewSize設為一致) |
堆的1/3 |
-XX:MetaspaceSize | 元數據區大小 | 20.8M |
-XX:MaxMetaspaceSize | 元數據區最大值 | 4g |
-XX:NewSize | 年輕代默認大小 | 2m |
-XX:MaxNewSize | 年輕代最大值(根據 NewRatio計算) | |
-Xss | 每個線程的堆棧大小 | 1M |
-XX:NewRatio | 新生代和老年代比值 | 2 |
-XX:SurvivorRatio | Eden與Survivor的占用比例。 默認值8表示survivor占用2/8(兩個survivor),Eden占用6/8。 |
8 |
-XX:+AggressiveOpts | 啟用JVM開發團隊最新的調優成果。 例如編譯優化,偏向鎖,並行年老代收集等。 |
默認不啟用 |
--XX:MaxHeapFreeRatio | 空余堆內存大於70%時,JVM會減少堆直到 -Xms的最小限制。 | 70 |
--XX:MinHeapFreeRatio | 空余堆內存小於40%時,JVM就會增大堆直到-Xmx的最大限制。 | 40 |
-XX:-DisableExplicitGC | 禁止在運行期顯式地調用 System.gc()。 開啟該選項后,GC的觸發時機將由Garbage Collector全權掌控。 |
默認不啟用 |
-XX:-UseConcMarkSweepGC | 啟用CMS低停頓垃圾收集器 | 默認不啟用 |
-XX:+UseParNewGC | 新生代並行回收 | 默認不啟用 |
-XX:+ScavengeBeforeFullGC | 在Full GC前觸發一次Minor GC | 默認啟用 |
-XX:ParallelGCThreads | 並行收集器線程數 | 如果cpu線程數<=8則使用cpu線程數,否則增加5/8的線程總數 |
-XX:ConcGCThreads | 並發垃圾收集器使用的線程數量 | XX:ParallelGCThreads/4 |
-XX:+UseG1GC | 使用g1回收器 | 默認不啟用 |
-XX:MaxGCPauseMillis | 最大GC停頓時間,這是個軟目標,JVM將盡可能(但不保證)停頓小於這個時間 | 200ms |
-XX:InitiatingHeapOccupancyPercent | 啟動並發GC周期時的堆內存占用百分比 | 45 |
-XX:G1ReservePercent | 設置堆內存保留為假天花板的總量,以降低提升失敗的可能性 | 10 |
-XX:G1HeapRegionSize | 使用G1時Java堆會被分為大小統一的的區(region)。此參數可以指定每個heap區的大小. 默認值將根據 heap size 算出最優解. 最小值為 1Mb, 最大值為 32Mb. | |
-XX:+CMSScavengeBeforeRemark | 在CMS GC前啟動一次ygc,目的在於減少old gen對ygc gen的引用,降低remark時的開銷-----一般CMS的GC耗時 80%都在remark階段 | 默認不啟用 |
-XX:CMSInitiatingOccupancyFraction | 堆內存使用達到70%時啟動cms gc | 70 |
-XX:+UseCMSInitiatingOccupancyOnly | 只是用設定的回收閾值(XX:CMSInitiatingOccupancyFraction),如果不指定,JVM僅在第一次使用設定值,后續則自動調整 | 默認不啟用 |
XX:+AlwaysPreTouch | 當JVM初始化時預先對Java堆進行預先摸底(Pre-touch),堆的每個頁初始化時滿足需求,而不是應用執行時遞增。 | 默認不啟用 |
2,jvm調優(g1)
由於java后續版本g1是主流,所以調優針對的是g1。
2.1,堆的大小上限一般不要超過32gb
在堆中,32位的對象引用占4個字節,而64位的對象引用占8個字節。也就是說,64位的對象引用大小是32位的2倍。java6之后支持
-XX:+UseCompressedOops
開啟指針壓縮,默認開啟。Enables the use of compressed pointers (object references represented as 32 bit offsets instead of 64-bit pointers) for optimized 64-bit performance with Java heap sizes less than 32gb.
指針壓縮原理:
32位內最多可以表示4GB,64位地址分為堆的基地址+偏移量,當堆內存<32GB時候,在壓縮過程中,把偏移量/8后保存到32位地址。在解壓時再把32位地址放大8倍,所以啟用CompressedOops的條件是堆內存要在4GB*8=32GB以內。
如果GC堆大小在4G以上32G以下,則啟用UseCompressedOop ,如果GC堆大小大於32G,壓指失效,使用原來的64位。
所以正常情況下,堆內存最大不要超過32gb。
2.2,使用g1的時候不能設置年輕代的大小(-Xmn)
在使用g1回收器的時候如果同時設置了-Xmn
參數,也就是指定了年輕代的大小,那么這將影響g1的回收,因為一旦設置了年輕代的大小,那么g1將無法動態調整堆的各區間的大小,同時g1的最大暫停時間目標將不再起作用。與此同時,最大暫停時間(-XX:MaxGCPauseMillis
)只是個期望值,g1無法絕對保證,而且設置最大暫停時間的值不能用平均響應時間來設置,應該用上限響應時間或者接近上限響應時間的值來設置。
2.3,解決回收過程中的轉移失敗(Evacuation Failure)
gc日志中常可以看到"evacuation failure", "to-space exhausted", "to-space overflow", "promotion failure"之類的輸出,這是由於g1在回收的過程中無法找到空閑空間放置存活對象,這種情況稱為Evacuation Failure(類比cms中的晉升失敗):
924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space exhausted), 0.1957310 secs]
924.897:[GC pause (G1 Evacuation Pause) (mixed) (to-space overflow), 0.1957310 secs]
這個易導致full gc,而g1中的full gc是Serial收集器,這會導致秒級的暫停時間,所以在g1中要盡量避免出現full gc。針對此情況可以做一下調整:
- 減少InitiatingHeapOccupancyPercent參數的值(默認45)提前啟動標記周期,但同時也會增加GC發生頻率;
- 增加ConcGCThreads參數的值來增加並發標記的線程數目,提高gc的效率,但同時也會占用更多工作線程的資源;
- 增加 -XX:G1ReservePercent參數的值(並相應增加總的堆大小),為"目標空間"(to-space)增加預留內存量。
2.4,巨型對象分配(Humongous Allocation)
對於 G1 GC,任何超過區域(G1HeapRegionSize)一半大小的對象都被視為“巨型對象”。此類對象直接被分配到老年代中的“巨型區域”。這些巨型區域是一個連續的區域集。StartsHumongous
標記該連續集的開始,ContinuesHumongous
標記它的延續。
g1只會在標記周期結束的時候清理巨型對象,或者在full gc的時候其不可達。巨型對象不會移動,即使是full gc時也是如此,這會過早的減慢full gc的效率。
由於每個 StartsHumongous 和 ContinuesHumongous 區域集只包含一個巨型對象,所以沒有使用巨型對象的終點與上個區域的終點之間的空間(即巨型對象所跨的空間)。如果對象只是略大於堆區域大小的倍數,則此類未使用的空間可能會導致堆碎片化。
巨型對象分配日志示例:
280.008: [G1Ergonomics (Concurrent Cycles) request concurrent cycle initiation, reason: occupancy higher than threshold, occupancy: 62344134656 bytes, allocation request: 46137368 bytes, threshold: 42520176225 bytes (45.00 %), source: concurrent humongous allocation]
如果巨型分配導致連續的並發周期,並且此類分配導致老年代碎片化,可以增加 -XX:G1HeapRegionSize
,這樣一來,之前的巨型對象就不再是巨型對象了,而是采用常規的分配路徑,或者分析程序本身以減少此類對象的產生。-XX:G1HeapRegionSize,其值為2的次冪,最小值為 1mb, 最大值為 32mb。
2.5,垃圾回收算法CMS和G1的選擇
程序調優的兩個目標特點:
指標 | 定義 |
---|---|
響應能力 | 響應能力又或者延時(Latency)指系統對任務的響應速度,比如有人機交互的系統(gui程序,web界面)。響應能力優先的系統,對系統長時間的卡頓是無法接受的。 |
吞吐量 | 吞吐量(Throughput)指系統單位時間內處理任務的能力,吞吐量優先的系統,更需要考慮的是系統處理大量任務的效率,至於單次任務的效率無足輕重,所以卡頓是可以接受的,只要整體效率有保障。 |
響應能力和吞吐量是衡量系統性能的兩個重要指標,這兩個指標並不是絕對對立的,最終系統的表現取決於系統的瓶頸。
類別 | 優點 | 缺點 | 適用場景 |
---|---|---|---|
CMS | 並發收集、低停頓 | 對cpu資源敏感; 無法處理浮動垃圾; 容易出現內存空間碎片; |
對響應時間敏感,cpu資源豐富, 追求服務的響應速度, 相應犧牲服務的吞吐量。 |
G1 | 無內存空間碎片的問題; 可預測的停頓; 配置少,可動態調優至最優配置 |
g1觸發full gc時會退化使用Serial收集器進行回收,導致秒級的暫停時間 | 面向服務端,適用於多核,大內存的服務端系統。 實現高吞吐量的同時,盡可能滿足gc暫停時間的要求 |
2.6 jvm參數示例
### g1
-server
-Xms10g
-Xmx10g
-XX:+AlwaysPreTouch
-XX:+UseG1GC
-XX:+ScavengeBeforeFullGC
-XX:+DisableExplicitGC
### cms
-server
-Xms10g
-Xmx10g
-XX:+AlwaysPreTouch
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-XX:+CMSPermGenSweepingEnabled
-XX:+ScavengeBeforeFullGC
-XX:+CMSScavengeBeforeRemark
-XX:+DisableExplicitGC
3,jvm 日志
3.1 gc日志參數
參數 | 功能 |
---|---|
-verbose:gc | 輸出一些詳細的gc信息(等同 -XX:+PrintGC), -XX:+PrintGC后續版本棄用 |
-XX:+PrintGCDetails | 輸出gc的詳細信息 |
-XX:+PrintGCTimeStamps | 輸出GC的時間戳(以基准時間的形式) |
-XX:+PrintGCDateStamps | 輸出GC的時間戳(以日期的形式) |
-XX:+PrintAdaptiveSizePolicy | 打印自適應收集的大小,默認關閉 |
-XX:+UseGCLogFileRotation | 打開或關閉GC日志滾動記錄功能,要求必須設置 -Xloggc參數,並且開啟后默認的文件數和文件大小不受限制 |
-XX:NumberOfGCLogFiles | 設置滾動日志文件的個數,必須大於1 |
-XX:GCLogFileSize | 設置滾動日志文件的大小,默認8k |
-Xloggc:[file] | 將gc信息輸出到單獨的日志文件,示例: Xloggc:/path/to/gc/logs/log.txt |
3.2 gc日志解讀
- cms日志示例:
[GC [ParNew: 471013K->44702K(471872K), 0.0151339 secs] 1092059K->673523K(2044736K), 0.0154045 secs] [Times: user=0.18 sys=0.04, real=0.02 secs]
[Full GC [PSYoungGen: 1403K->33K(912504K)] [ParOldGen: 8K->1261K(1048576K)] 1411K->1261K(1926080K), [Metaspace: 3508K->3508K(1056768K)], 0.0083870 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
各個指標對應的含義:
[GC類型(導致原因) [發生區域: gc前大小->gc后大小(總大小), gc占用時間] gc前堆大小->gc后堆大小(堆總大小), 該內存區gc占用時間] [Times: 用戶態耗時, 內核態耗時, 實際耗時(wall clock time)]
注意:Minor GC,Major GC均會導致STW
-
G1日志示例
0.522: [GC pause (young), 0.15877971 secs]
這是一個轉移暫停,距離進程啟動的0.522秒開始,所有被轉移的是年輕代分區,一共花費了0.15877971秒。
轉移暫停也可以是混合的,比如:1.730:[GC pause (mixed), 0.32714353 secs],此時分區包含所有的年輕代分區和部分老年代分區。
[Parallel Time: 157.1 ms] 並行GC Worker線程的總耗時,下面縮進部分是worker線程的子任務 [GC Worker Start (ms): 522.1 522.2 522.2 522.2 每個worker線程的啟動時間(距離jvm啟動的時間) Avg: 522.2, Min: 522.1, Max: 522.2, Diff: 0.1] 所有線程啟動時間的avg,min,max,diff(下同,不贅述) [Ext Root Scanning (ms): 1.6 1.5 1.6 1.9 每個線程掃描Roots(全局變量,寄存器,線程棧,vm數據結構)的時間 Avg: 1.7, Min: 1.5, Max: 1.9, Diff: 0.4] 同上 [Update RS (ms): 38.7 38.8 50.6 37.3 每個線程更新Remember Set(RSet)時間,RSet保存引用 Avg: 41.3, Min: 37.3, Max: 50.6, Diff: 13.3] [Processed Buffers : 2 2 3 2 Sum: 9, Avg: 2, Min: 2, Max: 3, Diff: 1] [Scan RS (ms): 9.9 9.7 0.0 9.7 掃描RSet的時間,每個分區的RSet包含指向分區的Card。這個階段掃描CSet集合中所有指向分區的Card。 Avg: 7.3, Min: 0.0, Max: 9.9, Diff: 9.9] [Object Copy (ms): 106.7 106.8 104.6 107.9 拷貝CSet集合里面所有分區存活對象到另一個分區的時間。 Avg: 106.5, Min: 104.6, Max: 107.9, Diff: 3.3] [Termination (ms): 0.0 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.0, Diff: 0.0] [Termination Attempts : 1 4 4 6 Sum: 15, Avg: 3, Min: 1, Max: 6, Diff: 5] [GC Worker End (ms): 679.1 679.1 679.1 679.1 每個線程的停止時間 Avg: 679.1, Min: 679.1, Max: 679.1, Diff: 0.1] [GC Worker (ms): 156.9 157.0 156.9 156.9 每個線程的耗時 Avg: 156.9, Min: 156.9, Max: 157.0, Diff: 0.1] [GC Worker Other (ms): 0.3 0.3 0.3 0.3 每個線程執行除了上面操作的其他任務的耗時 Avg: 0.3, Min: 0.3, Max: 0.3, Diff: 0.0] [Clear CT: 0.1 ms] 串行清除Card Table的時間
[Other: 1.5 ms]
[Choose CSet: 0.0 ms] 為CSet選擇Region的時間
[Ref Proc: 0.3 ms] 處理對象引用的時間
[Ref Enq: 0.0 ms] 引用入ReferenceQueues隊列的時間
[Free CSet: 0.3 ms] 釋放CSet時間
[Eden: 12M(12M)->0B(10M) Survivors: 0B->2048K Heap: 13M(64M)->9739K(64M)]
Eden在回收之前容量和占用都是12MB,回收之后占用為0,容量為13MB(有新的分區加入Eden)。
Survivor回收之后,占用從0變到2048KB,整個堆在回收之前占用和容量是14MB和64MB,回收之后是9739KB和64MB。
[Times: user=0.59 sys=0.02, real=0.16 secs]
## 3.3 gc日志可視化
可以使用`gcviewer`對gc日志進行可視化,這樣可以更直觀的觀察和分析gc日志,其地址為:
[https://github.com/chewiebug/GCViewer](https://github.com/chewiebug/GCViewer)
參考鏈接:
[https://blog.csdn.net/Dax1n/article/details/77163540](https://blog.csdn.net/Dax1n/article/details/77163540)
https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
[https://juejin.im/post/5c4c8ad9f265da6179752b03](https://juejin.im/post/5c4c8ad9f265da6179752b03)
[https://www.cnblogs.com/happyflyingpig/p/8918675.html](https://www.cnblogs.com/happyflyingpig/p/8918675.html)
[https://segmentfault.com/a/1190000007815623](https://segmentfault.com/a/1190000007815623)
[https://blog.51cto.com/14237164/2379588](https://blog.51cto.com/14237164/2379588)
[https://www.oracle.com/technetwork/cn/articles/java/g1gc-1984535-zhs.html](https://www.oracle.com/technetwork/cn/articles/java/g1gc-1984535-zhs.html)
[http://www.raincent.com/content-85-4354-5.html](http://www.raincent.com/content-85-4354-5.html)