簡介
想了解JDK12,13,14中的GC調優秘籍嗎?想知道這三個版本中JVM有什么新的變化嗎?
一起來看看這期的GC調優秘籍,因為JDK12,13,14中的GC變化不太大,所以這里一起做個總結,文末附有相應的PDF下載,希望大家能夠喜歡。
那些好用的VM參數
我們再講幾個之前的版本中沒有講過的比較好用的VM參數。
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=path
我們寫java程序的,經常會碰到程序報java.lang.OutOfMemoryError異常,這時候優秀的我們是怎么解決的呢?
高級程序員一看到這個錯誤,就知道heap空間不夠用了,加大heap空間吧。
但是聰明的程序員可能就會問了,為什么會出現這個OutOfMemoryError異常呢?是不是我們程序里面有沒有問題呢?
帶着這個疑問,聰明的程序員可能會使用jmap命令將heap dump出來,甚至有些程序員可以熟練的使用jcmd pid GC.heap_info命令來查看heap info了。
這些都很好,但是如果使用上面兩個JVM選項,程序只要出現OutOfMemoryError,就會自動將heap dump出來,默認的文件名是java_pid.hprof ,你也可以自己指定文件路徑。
-XX:+PrintClassHistogram
有時候,我們需要統計class的信息,那么可以使用這個選項。
在windows環境中收到Control+C,或者在linux環境中收到Control+Break信號的時候就會觸發相應的統計事件。
這個參數和 jmap -histo command 或者 jcmd pid GC.class_histogram效果是一樣的。
有小伙伴要問了,Control+C和Control+Break信號是什么鬼?怎么將信號傳遞給java程序呢?
這里給大家擴展講一下,發送信號可以用kill命令。
kill其實有兩種用法。
第一種 kill pid,kill后面直接跟一個pid。
第二中 kill -TERM pid, TERM就是我們要向kill傳遞的信號。
其實kill pid 就是 kill -15 pid的簡寫。
我們是用kill -l來看一下kill支持的信號類型:
kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
我們常用的9=SIGKILL,也就是向JVM傳遞一個強制kill的信號。
注意,這些信號中,除了9這個信號可以無條件終止進程,其他的信號進程都有權利忽略。
所以有時候我們使用kill pid命令去終止進程,但是進程沒反應。不是因為進程壞了,而是因為進程忽略掉了你發出的信號。
-XX:+PrintConcurrentLocks
同樣的,PrintConcurrentLocks也是收到Control+Break或者Control+C信號時,輸出java.util.concurrent的lock信息。
這個參數和jstack -l 或者jcmd pid Thread.print -l效果是一樣的。
-XX:+PrintFlagsRanges
再來看一個比較有用的參數PrintFlagsRanges。有時候我們想使用某些VM的參數,但是不知道這些參數的取值范圍,那么可以使用PrintFlagsRanges。我們試一下:
是不是非常有用?
G1的變化
JVM在發展,G1的參數也在發展,這幾個版本中有幾個G1的參數名發生了變化:
-XX:DefaultMaxNewGenPercent 替換成為-XX:G1MaxNewSizePercent=percent
-XX:G1OldCSetRegionLiveThresholdPercent 替換成為-XX:G1MixedGCLiveThresholdPercent=percent
-XX:DefaultMinNewGenPercent替換成為-XX:G1NewSizePercent=percent
配置FlightRecorder
Java Flight Recorder(JFR)是JVM的診斷和性能分析工具。它可以收集有關JVM以及在其上運行的Java應用程序的數據。JFR是集成到JVM中的,所以JFR對JVM的性能影響非常小,我們可以放心的使用它。
一般來說,在使用默認配置的時候,性能影響要小於1%。
JFR是一個基於事件的低開銷的分析引擎,具有高性能的后端,可以以二進制格式編寫事件。
JFR是JVM的調優工具,通過不停的收集JVM和java應用程序中的各種事件,從而為后續的JMC分析提供數據。
Event是由三部分組成的:時間戳,事件名和數據。同時JFR也會處理三種類型的Event:持續一段時間的Event,立刻觸發的Event和抽樣的Event。
為了保證性能的最新影響,在使用JFR的時候,請選擇你需要的事件類型。
JFR從JVM中搜集到Event之后,會將其寫入一個小的thread-local緩存中,然后刷新到一個全局的內存緩存中,最后將緩存中的數據寫到磁盤中去。
或者你可以配置JFR不寫到磁盤中去,但是這樣緩存中只會保存部分events的信息。
FlightRecorder有兩部分的配置,第一部分是配置FlightRecorder本身的大小,存儲等信息。第二部分是FlightRecorder的開啟選項。
我們看下FlightRecorder相關的配置參數:
-XX:FlightRecorderOptions:parameter=value
下面是StartFlightRecording的配置:
-XX:StartFlightRecording=parameter=value
RAM參數
默認情況下,JVM的MaxHeapSize是根據RAM的大小來自動配置的,比如說,我有一個8G內存的機子,執行下面的命令:
java -XX:+PrintFlagsFinal -version | grep -Ei "maxheapsize|maxram"
可以看到MaxHeapSize= MaxRAM / MaxRAMPercentage。
VM也提供了下面幾個用來設置RAM相關的參數:
-XX:MaxRAM=size
-XX:InitialRAMPercentage
-XX:MaxRAMPercentage
-XX:MinRAMPercentage
主要就是設置最大的RAM值和Heap占RAM的比例。
RAM參數主要是為了java在容器中運行配置的。
JDK13中的ZGC
在JDK13中,我們可以開啟ZGC的體驗了。ZGC是一個可擴展的,低延遲的GC。ZGC是並發的,而且不需要停止正在運行的線程。
ZGC是在JDK11中被引入的。
我們通過下面的方式來開啟ZGC:
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
RTM支持
Restricted Transactional Memory(RTM)是受限的事務性存儲器,是Intel在x86微架構中所引入的指令集系統,它屬於TSX(Transactional Synchronization Extensions,事務性同步擴展)指令集擴展。
RTM主要用來在多線程環境中提升執行效率。
RTM引入了XBEGIN, XABORT, XEND和XTEST。通過將指令包含在XBEGIN和XEND之間,可以達到transaction的效果。
可以將RTM看做是一個粗粒度的鎖,XBEGIN和XEND之間包含的代碼就是要執行的程序。RTM可以由硬件自動檢測操作中的數據沖突,保證事務性操作的正確性,從而發掘操作間的並行性。
同時RTM還可以減少CPU cache line的false-sharing。
RTM支持主要有4個參數:
-XX:+UseRTMLocking
-XX:+UseRTMDeopt
-XX:RTMAbortRatio=abort_ratio
-XX:RTMRetryCount=count
其中UseRTMDeopt和RTMAbortRatio是聯合起來用的。
之前我們講到RTM會對粗粒度的鎖進行優化,但如果真的是多線程並發執行訪問同樣資源的時候,這個優化實際上是不成功的,會被abort,然后回退到正常的鎖狀態。
如果abort超出了一定的比例,則會將RTM代碼反優化。
總結
好了,就總結這么多。下面是JDK12,13,14的GC調優秘籍,歡迎下載。
本文作者:flydean程序那些事
本文鏈接:http://www.flydean.com/jdk12-13-14-gc-cheatsheet/
本文來源:flydean的博客
歡迎關注我的公眾號:程序那些事,更多精彩等着您!