1. 程式人生 > 其它 >jvm調優、垃圾回收器相關知識彙總

jvm調優、垃圾回收器相關知識彙總

進行jvm調優的目的就是為了降低full gc的頻次和每次full gc的時間,從而提高吞吐率(處理請求的時間/(處理請求的時間+垃圾回收的處理時間))或者縮短響應時間。

1.虛擬機器引數

-Xmx   //最大堆空間
-Xms   //初始堆空間大小;如果初始堆空間耗盡,jvm會對堆空間擴容,其擴充套件上限為最大堆空間。通常-Xms與-Xmx設定為同樣大小,避免擴容造成效能損耗
-Xmn   //新生代大小,一般設定為整個堆空間的1/3或者1/4
-XX:SurvivorRatio  //設定新生代中eden空間和from/to空間的比例關係。即-XX:SurvivorRatio=eden/from=eden/to

//例如: -Xmx20m -Xms20m -Xmn1m -XX:SurvivorRation=2   新生代大小為512kb(eden)+256kb(from)+256(to)=1MB,總可用新生代為512kb(eden)+256kb(from或者to)=768kb。(新生成的物件會分配在eden區,如果eden區佔滿會觸發minor gc,將不可回收的物件放入from或to,並且年齡+1)

-XX:NewRation   //設定新生代和老年待的比例。  -XX:NewRatio=老年代/新生代  例如:-Xmx20m -Xms20m --XX:NewRatio=2 新生代大小為20MB*1/3=6mb,老年代為13mb左右

//設定時應儘可能將物件預留在新生代,減少老年代GC的次數(FullGC)

-XX:MaxTenuringThreshold  //設定垃圾最大年齡。如果設定為0的話,則年輕代物件不經過survivor區,直接進入年老代。對於年老代比較多的應用,可以提高效率。如果將此值設定為一個較大值,則年輕代物件會在survivor區進行多次複製,可以增加物件在年輕代的存活時間,增加在年輕代即被回收的概率。
-XX:PretenureSizeThreshold  //另大於這個設定值的物件直接在老年代分配,避免在eden區及兩個survivor區之間發生大量的記憶體複製。pretenureSizeThreshold引數只對serial和parnew兩款收集器有效,parallel scavenge收集器一般並不需要設定。如果遇到必須使用此引數的場合,可以考慮ParNew加CMS的收集器組合。

-XX:+HeapDumpOnOutOfMemoryError   //當發生記憶體溢位時匯出堆資訊
-XX:+HeapDumpPath  //當發生記憶體溢位時匯出堆資訊指定輸出的存放路徑。 -XX:+HeapDumpPath=/opt/OOM.dump
-XX:OnOutOfMemoryError   //當發生記憶體溢位時可以執行指定指令碼   如:-XX:OnOutOfMemoryError=$JAVA_HOME/bin/Printstack

參考部落格:https://www.cnblogs.com/hanlinhu/p/9487049.html

2.典型垃圾回收器

  • Serial/Serial Old收集器是最基本最古老的收集器,它是一個單執行緒收集器,並且在它進行垃圾收集時,必須暫停所有使用者執行緒。Serial收集器是針對新生代的收集器,採用的是Copying演算法,Serial Old收集器是針對老年代的收集器,採用的是Mark-Compact演算法。它的優點是實現簡單高效,但是缺點是會給使用者帶來停頓。
  • ParNew:ParNew收集器是Serial收集器的多執行緒版本,使用多個執行緒進行垃圾收集。
  • Parallel Scavenge收集器是一個新生代的多執行緒收集器(並行收集器),它在回收期間不需要暫停其他使用者執行緒,其採用的是Copying演算法,該收集器與前兩個收集器有所不同,它主要是為了達到一個可控的吞吐量。
  • Parallel Old是Parallel Scavenge收集器的老年代版本(並行收集器),使用多執行緒和Mark-Compact演算法。
  • CMS(Current Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器,它是一種併發收集器,採用的是Mark-Sweep演算法。
  • G1收集器是當今收集器技術發展最前沿的成果,它是一款面向服務端應用的收集器,它能充分利用多CPU、多核環境。因此它是一款並行與併發收集器,並且它能建立可預測的停頓時間模型。

說明:

-XX:+UseParallelGC
指 定在 New Generation 使用 parallel collector, 並行收集 , 暫停 app threads, 同時啟動多個垃圾回收 thread, 不能和 CMS gc 一起使用 . 系統噸吐量優先 , 但是會有較長長時間的 app pause, 後臺系統任務可以使用此 gc。UseParallelGC是jdk1.7選擇parallel 回收器預設開啟的。
-XX:+UseParNewGC


指定在 New Generation 使用 parallel collector, 是 UseParallelGC 的 gc 的升級版本 , 有更好的效能或者優點 , 可以和 CMS gc 一起使用。UseParNewGC需要使用者自己手動開啟。

參考博文:https://blog.csdn.net/besokuse233/article/details/100915072、https://blog.csdn.net/lxlmycsdnfree/article/details/81531363?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1.no_search_link

parallel scavenge與parnew區別:parallel scavenge同樣是一個使用複製演算法的並行的多執行緒新生代收集器,但是它的關注點與其他收集器不同,CMS等收集器的關注點是儘可能地縮短垃圾收集時使用者執行緒的停頓時間,而Parallel Scavenge收集器的目標則是達到一個可控制的吞吐量(Throughput)。

停頓時間越短就越適合需要與使用者互動的程式,良好的響應速度能提升使用者體驗,而高吞吐量則可以高效率地利用CPU時間,儘快完成程式的運算任務,主要適合在後臺運算而不需要太多互動的任務

Parallel Scavenge收集器提供了兩個引數用於精確控制吞吐量,分別是控制最大垃圾收集停頓時間的-XX:MaxGCPauseMillis引數以及直接設定吞吐量大小的-XX:GCTimeRatio引數。

G1回收器的優勢和不足

與其他GC收集器相比,G1使用了全新的分割槽演算法。G1在回收期間,可以有多個GC執行緒同時工作,有效利用多核計算能力。此時使用者執行緒STW(並行)。 G1擁有與應用程式交替執行的能力,部分工作可以和應用程式同時執行,因此,一般來說,不會在整個回收階段發生完全阻塞應用程式的情況(併發)。

從分代上看,G1依然屬於分代型垃圾回收器,它會區分年輕代和老年代,年輕代依然有Eden區和Survivor區。但從堆的結構上看,它不要求整個Eden區、年輕代或者老年代都是連續的,也不再堅持固定大小和固定數量。

相較於CMS,G1還不具備全方位、壓倒性優勢。比如在使用者程式執行過程中,G1無論是為了垃圾收集產生的記憶體佔用(Footprint)還是程式執行時的額外執行負載(Overload)都要比CMS要高。從經驗上來說,在小記憶體應用上CMS的表現大概率有優先與G1,而G1在大記憶體應用上則發揮其優勢。平衡點在6-8GB之間。

參考博文:https://www.jianshu.com/p/8832fd7e2289

3.調優策略

對於JVM的垃圾回收器影響因素較多,例如:IO、臨時變數、常駐物件、物件大小、CPU等各種軟硬體配置,需要滿足的場景也存在差異,例如:吞吐量量優先、響應耗時優先,

  • 如果程式中較多的是“臨時變數”的話,可以通過設定適當的年輕代大小,是多數垃圾物件在minor gc時進行回收
  • 設定合理的from/to區大小,避免臨時物件(如果一批物件大於了from區的50%)直接進入老年代
  • 年輕代設定過大的話,進行minor gc耗時就會增加。

推薦博文:JVM垃圾收集器選擇策略-https://blog.csdn.net/weixin_43230063/article/details/86582050

JVM調優之垃圾回收器選擇-https://www.cnblogs.com/dengq/p/13687713.html

4.調優工具arthas

jps工具:檢視當前系統中有哪些java程序。

jmap:檢視堆記憶體佔用情況。 jmap -heap 程序id (只能檢測某個時間點)

jconsole工具:圖形介面的、多功能的監測工具,可以連續監測

jvisualvm:升級版的jConsole。

舉例:先jps檢視程序id ,再jmap -heap 程序id檢視堆記憶體情況。cmd中輸入jconsole出現圖形介面的

arthas阿爾薩斯的使用

  1. 下載arthas-boot.jar,並通過java -jar arthas-boot.jar啟動

  2. 在控制檯輸入編號,選擇要繫結的具體java程式,進入互動模式

  3. 常用的主要命令:

    dashboard 儀表盤
    thread 檢視當前執行緒, 如: thread -b 檢視當前阻塞其他執行緒的執行緒
    jvm 檢視當前jvm資訊
    sc 檢視JVM已載入的類資訊 ,“Search-Class” 的簡寫,這個命令能搜尋出所有已經載入到 JVM 中的 Class 資訊
    sm 檢視已載入類的方法資訊,“Search-Method” 的簡寫,這個命令能搜尋出所有已經載入了 Class 資訊的方法資訊
    jad 反編譯class檔案,如: jad java.lang.String
    monitor 監控方法執行情況,如: monitor -c 5 demo.MathGame primeFactors,統計該方法5個週期沒的執行狀況
    watch方法執行資料觀測,如: watch demo.MathGame primeFactors "{params,returnObj}"-x 2,-x代表遍歷深度
    trace 方法內部呼叫路徑,並輸出方法路徑上的每個節點上耗時,如: trace demo.MathGame run '#cost > 10',展示耗時大於4ms的呼叫路徑
    stack 輸出當前方法被呼叫的呼叫路徑,如: stack demo.MathGame primeFactors
    tt TimeTunnel,時空隧道,法執行資料的時空隧道,記錄下指定方法每次呼叫的入參和返回資訊,並能對這些不同的時間下呼叫進行觀測.使用 -p引數可以重新模擬請求
    watch/stack/trace這個三個命令都支援#cost
    

    參考博文:https://blog.csdn.net/li646495946/article/details/106970270/?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.no_search_link&spm=1001.2101.3001.4242.0

    https://blog.csdn.net/hhj13978064496/article/details/110876005

    https://www.jianshu.com/p/def57f3df566

既要仰望星空,又要腳踏實地