天天看點

jvm性能優化1 JVM記憶體模型2 調優診斷工具3 垃圾回收過程4 調優目的:減少full gc的頻率-STW(Stop The World)

文章目錄

  • 1 JVM記憶體模型
  • 2 調優診斷工具
    • 2.1 jvisualvm
    • 2.2 阿裡arthas
      • 2.2.1 直接下載下傳jar包運作
      • 2.2.2 常用指令
  • 3 垃圾回收過程
    • 3.1 垃圾回收機制
    • 3.2 回收過程
      • 3.2.1 minor gc:當Eden區放滿,回收新生代空間
      • 3.2.2 新生代轉移到老年代
        • 3.2.2.1 長期存活的對象
        • 3.2.2.2 Survivor區域存滿,會把這些對象拷貝老年代
        • 3.2.2.3 大對象進入老年代
        • 3.2.2.4 對象動态年齡判斷
      • 3.2.3 full gc:回收整個堆空間
  • 4 調優目的:減少full gc的頻率-STW(Stop The World)
    • 4.1 為什麼要設計STW?

1 JVM記憶體模型

jvm性能優化1 JVM記憶體模型2 調優診斷工具3 垃圾回收過程4 調優目的:減少full gc的頻率-STW(Stop The World)

2 調優診斷工具

2.1 jvisualvm

2.2 阿裡arthas

2.2.1 直接下載下傳jar包運作

java -jar arthas-boot.jar
           

2.2.2 常用指令

1、dashboard 顯示所有線程的執行情況

jvm性能優化1 JVM記憶體模型2 調優診斷工具3 垃圾回收過程4 調優目的:減少full gc的頻率-STW(Stop The World)

可以看到上述程式執行的堆記憶體情況(Eden區、Survivor區,old區,元空間,gc等)

2、thread [threadId] 顯示某個thread的詳細情況

3、thread -b 顯示阻塞情況

4、反編譯:jad com.hd.Test

反編譯可以幫助開發人員确定代碼是否成功釋出

3 垃圾回收過程

3.1 垃圾回收機制

可達性分析。從GC ROOT(棧裡的局部變量,方法區的靜态變量,常量)找到可達的對象,标記這些對象是非垃圾。

3.2 回收過程

3.2.1 minor gc:當Eden區放滿,回收新生代空間

  • 通過可達性分析标記Eden區域和S0區域的垃圾
  • 執行gc回收
  • 将Eden和S0的非垃圾對象複制到S1區,将他們的年齡+1.
  • 結束回收。後續回收的空間是Eden和S1。

3.2.2 新生代轉移到老年代

3.2.2.1 長期存活的對象

預設15歲,CMS預設6歲。通過參數

XX:MaxTenuringThreshold

設定。

3.2.2.2 Survivor區域存滿,會把這些對象拷貝老年代

3.2.2.3 大對象進入老年代

大對象就是需要大量連續存儲空間的對象(比如字元串、數組等)。

JVM參數

-XX:PretenureSizeThreshold

可以設定大對象的大小。如果超過這個值則對象直接進入老年代。該參數隻在

Serial

ParNew

兩個收集器下有效。

好處:避免大對象配置設定記憶體時的複制操作而降低效率

3.2.2.4 對象動态年齡判斷

年齡1+年齡2+年齡3+年齡N的對象加起來的空間,大于survivor區域的一半(具體的比例通過參數

-XX:TargetSurvivorRatio

設定),就會讓年齡N和年齡N以上的對象進入老年代。動态年齡判斷應該是這樣子的。說的通俗一點:就是年齡從小到大對象的占據空間的累加和,而不是某一個特定年齡對象占據的空間。

案例:億級網站搶購活動分析

jvm性能優化1 JVM記憶體模型2 調優診斷工具3 垃圾回收過程4 調優目的:減少full gc的頻率-STW(Stop The World)

3.2.3 full gc:回收整個堆空間

1、當老年代存滿時,會觸發full gc

2、調用System.gc()方法

4 調優目的:減少full gc的頻率-STW(Stop The World)

minor gc和full gc都會導緻STW,導緻應用程式暫停。

如果gc時間比較長,則STW時間也會很長,就會造成程式響應很慢。

4.1 為什麼要設計STW?

如果不STW有什麼壞處?【對象狀态在使用者線程執行過程中不斷變化,造成錯标記或漏标記】

  • gc過程中,使用者線程還在進行,可能會出現gc到一半的時候,已經判斷為非垃圾的對象變成了垃圾(漏标記)。
  • gc已經被标記為垃圾的對象,使用者線程後續繼續使用了(錯标記)。