"簡單"的jvm調優

聆聽的車轍發表於2019-02-15

"簡單"的jvm調優
    作為一名勵志成為"神奇寶貝大師"的男人,怎麼能連JVM都不懂呢,不然你可能會像智爺那樣,一輩子拿不到冠軍了。
    java能在多平臺執行的基礎就是java虛擬機器了,這邊我們不談論它的記憶體區域,畢竟jdk7的方法區和jdk8元空間還是有區別的。

jvm引數

//常見引數
-Xms1024m 初始堆大小 
-Xmx1024m 最大堆大小  一般將xms和xmx設定為相同大小,防止堆擴充套件,影響效能。
-XX:NewSize=n:設定年輕代大小 
-XX:NewRatio=n:設定年輕代和年老代的比值.如:為3,表示年輕代與年老代比值為1:3,年輕代佔整個年輕代年老代和的1/4 
-XX:SurvivorRatio=n:年輕代中Eden區與兩個Survivor區的比值.注意Survivor區有兩個.如:3,表示Eden:Survivor=3:2,一個Survivor區佔整個年輕代的1/5 
-XX:MaxPermSize=n:設定持久代大小
-XX:+HeapDumpOnOutOfMemoryError OOM時自動儲存堆檔案,可以用visualvm分析堆檔案

//收集器設定 
-XX:+UseSerialGC:設定序列收集器 
-XX:+UseParallelGC:設定並行收集器 
-XX:+UseParalledlOldGC:設定並行年老代收集器 
-XX:+UseConcMarkSweepGC:設定併發收集器

//垃圾回收統計資訊 
-XX:+PrintGC 
-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-Xloggc:filename

//並行收集器設定 
-XX:ParallelGCThreads=n:設定並行收集器收集時使用的CPU數.並行收集//執行緒數. 
-XX:MaxGCPauseMillis=n:設定並行收集最大暫停時間 
-XX:GCTimeRatio=n:設定垃圾回收時間佔程式執行時間的百分比.公式為1/(1+n)
//併發收集器設定 
-XX:+CMSIncrementalMode:設定為增量模式.適用於單CPU情況. 
-XX:ParallelGCThreads=n:設定併發收集器年輕代收集方式為並行收集時,使用的CPU數.並行收集執行緒數.
複製程式碼

用法

Idea用法
  1. 開啟idea
  2. 點選右上角 edit configurations
  3. 在vm options輸入引數

"簡單"的jvm調優

Springboot用法

由於筆者一直用的是Springboot,因此這邊以Springboot的形式進行示範,在啟動專案jar包時新增引數。

java -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC newframe-1.0.0.jar
複製程式碼

工具使用

Visual VM

Visual VM 由java編寫,已經被jdk整合,通過檢測 JVM 中載入的類和物件資訊等幫助我們分析記憶體使用情況,是用來分析java專案 、調優的利器,功能強大。

"簡單"的jvm調優
概述:顯示了專案的jvm引數。
這邊的禁用是什麼原因呢?相信直播間的觀眾應該都是有智慧的!
監視: {} 暫時省略n個字。
執行緒: {} 暫時省略n個字。
抽樣器: {} 暫時省略n個字。

jstat

1. 檢視專案程式PId
  1. 筆者這邊採用docker部署Springboot專案,所以只需要top或者jps就能直接檢視到Pid。
  2. lsof -i:埠號,前提是你已經安裝了。
  3. ps -ef | grep 專案名
2. 使用命令檢視結果
jstat -gcutil 5 1000
複製程式碼

"簡單"的jvm調優

實戰分析

"簡單"的jvm調優

"簡單"的jvm調優
"簡單"的jvm調優

  1. 通過Visual VM發現,基本上每隔8分鐘,jvm就會發生一次GC,而我本人也沒有訪問過專案,專案的訪問量應該為0,所以在沒有定時任務或者死迴圈的情況下,產生的物件數應該為0。理論上是不會發生GC的。
  2. 那麼GC是發生在哪裡的呢?年輕代還是老年代?
    由於這邊NewRatio 為1,所以不管是老年代或者新生代發生gc一般都是在200m左右,我們不好分辨是哪個代。其實之前NewRatio=2xmx450m,發生GC的情況是150m。因此是新生代發生了GC。
  3. 如果不相信,下面是用jstat的截圖,可以看出是新生代物件在不停的產生。

"簡單"的jvm調優
4. 知道是新生代發生了GC,基本上已經證明了上述的猜想:有個死迴圈。通過抽象分析器發現char物件非常大。

"簡單"的jvm調優
5. 接下來可以通過堆dump發現是哪幾句程式碼出現了問題。可以使用jhat這個工具,檔案可以通過Visual VM產生,當然在OOM的情況下,也可以通過引數產生。

jhat -J-Xmx1024M file
複製程式碼

分析堆dump應該就可以發現了,這邊就不分析了,其實是重啟專案,對映多個埠,然後等待GC,就比較麻煩。為了更加貼近實際,該專案屬於真實專案,已部署到阿里雲,連結在此,猛戳我,程式碼來源於github。

結語

最後祝大家新年快樂,找到好工作。希望小智慧拿個冠軍,都看了十幾年了,圓了老玩家的夢吧。

"簡單"的jvm調優

相關文章