idea中設置JVM參數,簡單理解JVM常見參數,JVM調優簡單入門
前面學習了JVM的內存分布,今天就來驗證下。順便通過測試學習一下JVM的幾個參數,不過測試是在idea中,所以先要在idea上設置JVM參數。
一、idea設置全局的JVM參數
一共三步,第一步在菜單欄Help下選擇Edit Customer VM Options.......
第二步:可以看到選中後的參數,然後就可以設置常規參數,設置完成後記得重啟idea。如下圖:
第三步:重啟後,查看結果,在idea的最右下角會顯示總的和使用的,如果沒有顯示可以設置顯示,如下圖,在setting中勾選紅色框那個選項,點擊應用完成。
二、針對應用配置JVM參數
第一步:選擇Run下面的Edit Configurations....
第二步:選擇想配置的應用,然後在右側的VM options設置JVM參數。
三、JVM內存驗證
又要祭出那張內存分布圖了,
如上圖,程序計數器不會拋出異常,先不管了,主要是剩下幾個的驗證。
1、Java堆驗證
從之前的學習知道,堆裡面放的都是對象和數組,主要是對象。首先是控制堆大小的兩個參數-Xms(初始堆大小)、-Xmx(最大對大小)。
測試應用的JVM參數設置:
-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
其中+HeapDumpOnOutOfMemoryError參數可以是內存溢出存儲內存快照,可用於分析錯誤。測試結果如下圖:
紅框內就是創建的文件就是內存快照文件,在你的項目的工作目錄下,這個是內存溢出前存儲的內存情況,可以用專門的工具去分析。這裡分享一個在線的分析網站,把Dump文件傳上去就可以簡單分析下了,網址就不打了,具體如下圖:
2、虛擬機棧和本地方法棧驗證
HotSpot虛擬機不區分虛擬機棧和本地方法棧(通過java -version可查看是什麼虛擬機),所以一起測試了。對應的JVM參數-Xss(每個線程的棧大小)
我們知道棧裡面存的是棧幀,棧幀對應的就是線程的方法,所以只要調用的方法多就可以測試出來,最好的辦法就是遞歸了。
測試應用的參數配置:
-Xss128k -XX:+HeapDumpOnOutOfMemoryError
測試結果如下圖:
虛擬機棧之前說過有兩種溢出,線程請求的棧深度大於虛擬機允許的深度,將拋出StackOverflowError異常。如果虛擬機棧可以動態擴展,當擴展的時候沒有申請到內存的時候拋出OutOfMemoryError。
這裡我們是第一種情況。對於第二種情況,如果在單線程的情況下棧去動態擴展導致內存不足,那麼應該也是屬於棧不能申請到更多空間,所以是棧溢出,可以明顯看出來OutOfMemoryError和StackOverflowError存在包含關係。如果在多個線程下。每個線程的棧都在擴展內存,就會耗光物理內存而造成了OutOfMemoryError。
一個機器的內存是有限的。建立過多線程導致的內存溢出。如果不能減少線程,那麼可以通過減少堆和減少棧容量來換取更多線程。這部分可以深入討論,主要討論各個模塊的關係,和各自的限制。
3、方法區驗證
方法區中主要存儲被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼。所以我們平時遇到的這類異常一般都是加載的類太多,比如spring這類的框架都會對類進行增強,都會使用到CGLib這類字節碼技術,增強的類越多,就需要越大的方法區來保證動態生態的Class可以加載入內存。
jdk8的方法區變成了元空間,使用的是直接內存。所以和jdk7使用的參數不一樣具體參數如下:
jdk7:-XX:PermSize=10m -XX:MaxPermSize=10m
jdk8:-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
結果如下圖:
jdk8的異常更加明顯,明確表明是了元空間內存溢出。
4、直接內存驗證
直接內存如果不設置和-Xmx(堆最大)一樣。可通過參數-XX:MaxDirectMemorySize來設置直接內存。直接內存一般和NIO有關,DirectByteBuffer中通過Unsafe去操作的直接內存,DirectByteBuffer是通過計算知道內存不足拋出的異常,unsafe.allocateMemory()才是去申請內存的方法。測試代碼如下圖:
測試參數:-Xms20m -XX:MaxDirectMemorySize=10m
直接內存的溢出比較簡單,dump文件也比較小。如果發現內存溢出也沒有明顯異常,dump文件比較小,那麼就應該想到可以能直接內存溢出,是不是程序中使用了NIO的原因。
四、總結
學習了幾個常用JVM參數,總結如下
OutOfMemoryError簡稱OOM,學習了幾個基本的內存溢出後,對以後才能有更好的幫助。工作中遇到了內存溢出時,能根據異常信息來判斷是那個區域的內存溢出,也知道什麼樣的代碼可能會造成這些區域會出現內存溢出,並且知道一些處理手段。