JVM性能優化入門指南

前言

入門JVM垃圾回收機制後,接下來可以學習性能調優了。主要有兩部分內容:

  • JDK工具的使用。
  • 調優策略。

兵器譜

jps

列出正在運行的虛擬機進程,用法如下:

jps [-option] [hostid]

選項

作用

q

只輸出LVMID,省略主類的名稱

m

輸出main method的參數

l

輸出完全的包名,應用主類名,jar的完全路徑名

v

輸出jvm參數

jstat

監視虛擬機運行狀態信息,使用方式:

選項

作用

gc

輸出每個堆區域的當前可用空間以及已用空間,GC執行的總次數,GC操作累計所花費的時間。

gccapactiy

輸出每個堆區域的最小空間限制(ms)/最大空間限制(mx),當前大小,每個區域之上執行GC的次數。(不輸出當前已用空間以及GC執行時間)。

gccause

輸出-gcutil提供的信息以及最後一次執行GC的發生原因和當前所執行的GC的發生原因。

gcnew

輸出新生代空間的GC性能數據。

gcnewcapacity

輸出新生代空間的大小的統計數據。

gcold

輸出老年代空間的GC性能數據。

gcoldcapacity

輸出老年代空間的大小的統計數據。

gcpermcapacity

輸出持久帶空間的大小的統計數據。

gcutil

輸出每個堆區域使用佔比,以及GC執行的總次數和GC操作所花費的事件。

比如:

jstat -gc 28389 1s

每隔1秒輸出一次JVM運行信息:

jmap

生成堆存儲快照,使用方式:

jstack

生成虛擬機當前時刻的線程快照,幫助定位線程出現長時間停頓的原因,用法:

jstack <pid>

Monitor

Monitor是 Java中用以實現線程之間的互斥與協作的主要手段,它可以看成是對象或者Class的鎖。每一個對象都有,也僅有一個 monitor。下面這個圖,描述了線程和 Monitor之間關係,以及線程的狀態轉換圖:

進入區(Entrt Set):表示線程通過synchronized要求獲取對象的鎖,但並未得到。

擁有者(The Owner):表示線程成功競爭到對象鎖。

等待區(Wait Set):表示線程通過對象的wait方法,釋放對象的鎖,並在等待區等待被喚醒。

線程狀態

  • NEW,未啓動的。不會出現在Dump中。
  • RUNNABLE,在虛擬機內執行的。
  • BLOCKED,等待獲得監視器鎖。
  • WATING,無限期等待另一個線程執行特定操作。
  • TIMED_WATING,有時限的等待另一個線程的特定操作。
  • TERMINATED,已退出的。

舉個例子:

線程狀態:

t1沒有搶到鎖,所以顯示BLOCKED。t2搶到了鎖,但是處於睡眠中,所以顯示TIMED_WAITING,有限等待某個條件來喚醒。 把睡眠的代碼去掉,線程狀態變成了:

t1顯示RUNNABLE,說明正在運行,這裏需要額外說明一下,如果這個線程正在查詢數據庫,但是數據庫發生死鎖,雖然線程顯示在運行,實際上並沒有工作,對於IO型的線程別隻用線程狀態來判斷工作是否正常。 把MyTask的代碼小改一下,線程拿到鎖之後執行wait,釋放鎖,進入等待區。

線程狀態如下:

兩個線程都顯示WAITING,這次是無限期的,需要重新獲得鎖,所以後面跟了on object monitor

再來個死鎖的例子:

線程狀態:

這個有點像哲學家就餐問題,每個線程都持有對方需要的鎖,那就運行不下去了。

調優策略

兩個基本原則:

  • 將轉移到老年代的對象數量降到最少。
  • 減少Full GC的執行時間。目標是Minor GC時間在100ms以內,Full GC時間在1s以內。

主要調優參數:

設定堆內存大小,這是最基本的。

  1. -Xms:啓動JVM時的堆內存空間。
  2. -Xmx:堆內存最大限制。

設定新生代大小。

新生代不宜太小,否則會有大量對象涌入老年代。

  1. -XX:NewRatio:新生代和老年代的佔比。
  2. -XX:NewSize:新生代空間。
  3. -XX:SurvivorRatio:伊甸園空間和倖存者空間的佔比。
  4. -XX:MaxTenuringThreshold:對象進入老年代的年齡閾值。

設定垃圾回收器

年輕代:-XX:+UseParNewGC。

老年代:-XX:+UseConcMarkSweepGC。

CMS可以將STW時間降到最低,但是不對內存進行壓縮,有可能出現“並行模式失敗”。比如老年代空間還有300MB空間,但是一些10MB的對象無法被順序的存儲。這時候會觸發壓縮處理,但是CMS GC模式下的壓縮處理時間要比Parallel GC長很多。

G1採用”標記-整理“算法,解決了內存碎片問題,建立了可預測的停頓時間類型,能讓使用者指定在一個長度爲M毫秒的時間段內,消耗在垃圾收集上的時間不得超過N毫秒。

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