跟我一起學JVM(四)——JVM調優總結與實例

Java虛擬機對於內存的管理和垃圾收集是虛擬機結構中非常重要的一環,對提升程序的性能和穩定性有着非常重要的作用

對於JVM的調優是沒有正確答案的,需要根據項目的實際情況來配置合適的JVM參數。

(一)儘量減少Full GC的發生

通過之前的學習,我們知道老年代發生的GC速度比新生代速度慢十倍左右,那麼如果想要提高性能,減少老年代的Full GC是非常有用的

如何減少Full GC的發生?
1.提高大對象進入老年代的難度,進入老年代的東西少了,執行Full GC的次數自然就變小了
2.確保對象的生命週期不會很長,並且不長時間佔用新生代內存空間,這樣大部分對象就可以在Minor GC被回收掉,不會被保留到老年代中。

(二)養成良好代碼編寫習慣,從源頭節約資源,避免佔用過多內存

實例:一個後臺RPC服務器,使用的64位虛擬機,平時對外服務的Minor GC時間30毫秒以內,用戶完全可以接受,但是業務上有個功能每十分鐘加載80MB的數據文件到內存進行數據分析,這些數據會在內存中形成100萬個HashMap<Long, Long> entry,此時的Minor GC將造成超過500毫秒的停頓,用戶肯定是接受不了的。

分析:此處我們可以大致計算一下使用HashMap去存儲的空間效率,該HashMap有效數據是key和value中存放的2*8B數據,但是一旦轉變成Long對象,則需要添加對象頭,存儲時候爲了內存對齊,又會浪費掉一部分的內存空間。綜上最後的空間效率大概是18%,剩下的82%空間可以說都是被浪費掉的。

結論:在編寫代碼的時候要選擇恰當的數據結構,提高空間利用效率,避免創造大對象從而造成老年代GC頻繁的問題。

(三)使用恰當的高性能硬件程序部署策略

目前在高性能硬件上部署程序有兩種方式
1.使用64位JDK來使用大內存
2.使用若干個32位虛擬機建立邏輯集羣利用硬件資源

分析:由於大內存雖然擴充了空間,但是內存回收會導致長時間的停頓,而且32位JDK性能測試結果普遍低於64位JDK,所以大部分網站依舊採用了第二種方式進行構建。

(四)考慮Java堆外內存的溢出錯誤

實例:有個學校B/S考試系統,32位,堆1.6G,在測試時候時不時出現內存溢出問題,通過jstat發現GC並不頻繁,新生代和老年代的內存空間也是正常情況,說明並不是Java堆的OOM,通過打印系統日誌找到異常堆棧,顯示在java.nio.ByteBuffer.allocateDirect…發生OOM錯誤。

分析:這是因爲直接內存可能會導致內存溢出,直接內存是在堆之外的內存空間,也是由Java虛擬機管轄,但是直接內存的垃圾回收只是發生在Full GC階段,虛擬機清理老年代時候順便也清理一下直接內存,但是如果老年代不需要清理,那麼直接內存也得不到清理。程序使用NIO又是非常佔用直接內存的資源的,所以直接內存空間就會發生OOM錯誤。

(五)分析JVM崩潰情況

實例:異步請求(客戶端向服務器發送HTTP請求後將請求和後續的過程委託給一個線程執行,而自己去做其他事情,所有的連接通信都由被委託的線程執行,這樣可以有效的提高系統運行效率)該系統運行一段時間後出現了進程崩潰的情況,查看日誌得到SocketException: Connection reset 這個錯誤是連接異常

分析:因爲異步處理連接,但是遠端服務器處理速度過慢,導致大量線程無法快速結束,始終處於等待狀態。隨着時間流逝,系統創建了大量線程,並且大部分都處於等待狀態。線程的堆積,資源的使用最終超過了虛擬機的承受能力,從而使JVM崩潰。

喜歡請三連哦~


Instagram: https://www.instagram.com/barrywzc/
Twitter: https://twitter.com/BarryWa34098316
Bilibili: https://space.bilibili.com/473161964
GitHub: https://github.com/wzcwzcwzc
Patreon: https://www.patreon.com/wzcspace
WeChat: wzcspace


Please leave a LIKE and SUBSCRIBE for more content!
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章