聊聊JVM怎麼調優(實戰)

語言: CN / TW / HK

這節我略去基礎部分了,不熟悉基礎的,可以看我之前的文章

1、細說jvm(一)、jvm執行時的資料區域

2、細說jvm(二)、java物件建立過程

3、細說jvm(三)、物件建立的記憶體分配

4、細說jvm(四)、垃圾回收演算法

5、細說jvm(五)、垃圾回收器入門

6、細說jvm(六)、垃圾回收器CMS詳解

7、細說jvm(七)、垃圾回收器G1

8、細說jvm(八)、垃圾回收器ZGC

一、堆記憶體大小和年輕代佔比

1、這個是個影響最大的配置,在機器配置允許的情況下,堆記憶體給的越大越好;另外,堆記憶體的最大和最小值一定要設定成一樣的,因為jvm堆記憶體擴容的時候會觸發full gc,元空間也一樣,最大記憶體和最小記憶體值設定成一樣的

2、年輕代的佔比一般來說是大一些比較好,因為這樣會減少young gc的次數(ZGC之前的回收器young gc都是STW的)

二、回收器應該怎麼去選擇

一般來說,現在的後端服務有兩種,一種是對延遲不是很敏感的,比如多數的資料處理、分析型別的應用(多為OLAP型),這種應用的GC回收器,一般是選擇### Parallel 和 Parallel Old,這哥兩都是以吞吐量為優先的垃圾回收器。另外一種應用是對延遲比較敏感的,一般應該選用G1。 ! 《深入理解java虛擬機器》這本書上說過,在記憶體比較小的情況下,應該選用CMS而不是G1,但是經過作者在各種場景和各種小記憶體情況下測試,G1都比CMS好了太多,所以作者從實際的角度出發,推薦在追求低延遲的場景下使用G1。

三、高併發場景(有難度的一個場景)

需要注意的是高併發的場景,這時候應該是去選擇低停頓而不是高吞吐量的回收器,因為ps回收器的這兩個哥們,在young gc和old gc的時候都是stw的,而G1的mixed gc的一些回收階段最少還是能夠和使用者執行緒併發去執行的,這樣會減少stw的時間。在高併發之下,一定要想辦法去減少stw,因為在高併發的時候的由於gc而導致的stw,這時候java程序中只有gc執行緒在活動,而gc的執行緒優先順序比較低,這樣的話,作業系統資源就更容易被分配去處理併發請求(注意執行緒優先順序不僅僅是java的概念),導致gc執行緒被分配到的時間變少,然後stw時間進一步增加,然後導致請求進一步堆積,進而導致gc效率進一步降低和頻率進一步升高的惡性迴圈。

四、其他簡單一些規範

1、棧大小

jvm預設是1M,但是其實大多數情況下256K足矣,這樣可以減少StackOverFlow的概率

2、堆記憶體/元空間最大最小值設定為一樣

這是因為不論是堆記憶體還是元空間,在動態擴容的時候,都會出發full gc,這個原理有點類似於陣列擴容。

3、OOM發生的時候dump日誌

這點就不必解釋太多了。

4、full gc前後dump

這一點要謹慎,因為dump其實是個很消耗資源的操作,僅僅用在測試環境,生產環境最好不要用。

5、線上嚴禁開jvm 的遠端debug

這也是個低階錯誤。

6、禁止顯式呼叫System.gc()

同上,也是低階錯誤,gc不要人為呼叫。

7、不要試圖通過引數將停頓時間控制的很短

這個是由於jvm的不可能三角所導致的,停頓時間非常短的時候,對應的gc的頻率就會增加,進而導致吞吐量降低。