JVM常用參數及用法例子

聲明:以下環境均是JDK1.8 
參考:實戰Java虛擬機
 
1 GC打印參數
-XX:+PrintGC
遇到GC就會打印日誌
 
-XX:+PrintGCDetails
打印更詳細信息,JVM退出前會打印JVM詳情
 
-XX:+PrintHeapAtGC
GC前後打印堆信息
 
-XX:+PrintGCTimeStamps
會在當前GC時,打印當前啓動後的時間(比如程序啓動了0.08s、0.88s之類的這個時間點)
 
-XX:+PrintGCApplicationConcurrentTime        打印程序執行時間
-XX:+PrintGCApplicationStoppedTime        打印程序結束時間
 
2 類加載/卸載的跟蹤
-verbose:class
跟蹤類的加載和卸載過程
 
3 堆參數配置
可用-Xms、-Xmx指定堆大小,以下是一個JVM參數設置的圖:
Image.png
上圖的參數如下:
1 新生代大小配置:-Xmn,新生代會減少老年代大小,一般設置爲堆的1/3或1/4
 
2 新生代eden與from/to比例關係及效果:
------------代碼----------------------------
        byte[] b = null;
        for (int i = 0; i < 10; i++) {
            b = new byte[1 * 1024 * 1024];
        }
--------------------------------------------
2.1 使用java -Xmx20m -Xms20m -XX:SurvivorRatio=2 -XX:+PrintGCDetails NewSizeDemo  結果如下:
Image [1].png
- 分析:首先設置了堆的大小爲20m,然後設置eden與from的比例=2,並打印了GC日誌。由於這裏新生代分配到3584K(Eden) + 1536K(From) = 5120K,並且循環遍歷10次,每次分配1m內存,eden區到第四次就不夠,要進行回收,通過GC確保新生代有足夠空間。
 
2.2 把程序的new byte[1 * 1024 * 1024] 改爲 new byte[5 * 1024 * 1024],這樣每次會分配5M內存,3584K(Eden空間大小)無法容納單次分配的5M大小,故所有空間分配只能分到老年代中(圖中老年代可見用了大概10M,剛好是2 * (5*1024*1024)),兩次內存分配,原因是老年代只有13M,最多隻能容納兩次內存分配,第三次就會回收。
Image [2].png
2.3 把new byte[5 * 1024 * 1024] 改爲 new byte[1 * 1024 * 1024],每次分配1m內存。然後使用參數如下:
# java -Xmx20m -Xms20m -Xmn15m -XX:SurvivorRatio=8 -XX:+PrintGCDetails NewSizeDemo
因爲上面參數修改棧的大小=15m,eden/from=8,所以eden區空間>10m,所以就算循環分配10m的空間,下面也不會進行一次回收。
Image [3].png
2.4 還可以通過-XX:NewRatio=n 來設置新生代/老年代 的比例。
2.5 當eden區大於當次分配內存(1M),並且from小於(1M)的話,新生代需要老年代做空間擔保,1MB數組會進入老年代。
看完上面的參數設置過程,我們再來回顧下下面的圖(好好回憶下):
Image [4].png
 
3 堆溢出處理
爲了記錄堆溢出時的信息,可添加如下參數:
-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/xxx.dump
以上在發生堆溢出時,就會輸出文件到xxx.dump,然後可用MAT分析(後面會講)
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章