JVM虛擬機(三):參數配置
在虛擬機運行的過程中,如果可以跟蹤系統的運行狀態,那麽對於問題的故障排查會有一定的幫助,為此,虛擬機提供了一些跟蹤系統狀態的參數,使用給頂的參數執行java虛擬機,就可以在系統運行時打印相關日誌,用於分析實際問題。我們進行迅疾參數配置,其實主要是圍繞著堆、棧、方法區進行配置。
堆分配參數
-XX:+PrintGC使用這個參數,虛擬機啟動後,只要遇到GC就會打印日誌。
-XX:+UserSerialGC 配置串行回收器
-XX:+PrintGCDetails可以查看詳細信息,包括各個區的情況
-Xms:設置java程序啟動時初始堆大小
-Xmx:設置java程序能獲得的最大堆大小
-Xmx20m -Xms5m -XX:+PringCommandLineFlags:可以將隱式或者顯示傳給虛擬機的參數輸出
package com.base001; public class Test01 { public static void main(String[] args) { //-Xms5m -Xmx20m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:+PrintCommandLineFlags //查看GC信息 System.out.println("max memory:" + Runtime.getRuntime().maxMemory()); System.out.println("free memory:" + Runtime.getRuntime().freeMemory()); System.out.println("total memory:" + Runtime.getRuntime().totalMemory()); byte[] b1 = new byte[1*1024*1024]; System.out.println("分配了1M"); System.out.println("max memory:" + Runtime.getRuntime().maxMemory()); System.out.println("free memory:" + Runtime.getRuntime().freeMemory()); System.out.println("total memory:" + Runtime.getRuntime().totalMemory()); byte[] b2 = new byte[4*1024*1024]; System.out.println("分配了4M"); System.out.println("max memory:" + Runtime.getRuntime().maxMemory()); System.out.println("free memory:" + Runtime.getRuntime().freeMemory()); System.out.println("total memory:" + Runtime.getRuntime().totalMemory()); } }
點擊右鍵Run As,再點擊Run configurations找到Arguments
這是給主函數傳遞一些參數,我們需要的是第二個VM arguments
往裏面添加以下參數
-Xms5m -Xmx20m -XX:+PrintGCDetails -XX:+UseSerialGC
分配5m的初始化大小 最大的大小為20m 打印GC詳細信息 使用串行的垃圾回收器
運行代碼控制臺出現:
總結:在實際工作中,我們可以直接將初始的堆大小與最大堆大小設置相等,這樣的好處是可以減少程序運行時的垃圾回收次數,從而提高性能。實際工作中一般這些參數都是配置到web容器或者tomcat中的。
註意:-XX開頭的一般都是設置jvm的參數,其它開頭的都是設置具體工程的參數。
堆裏新生代的分配
-Xmn:可以設置新生代的大小,設置一個比較大的新生代會減少老年代的大小,這個參數對系統性能以及GC行為有很大的影響,新生代大小一般會設置整個堆空間的1/3到1/4左右。
-XX:SURvivorRatio:用來設置新生代中eden空間和from/to空間的比例。含義:-XX:SurvivorRatio=eden/from=eden/to
package com.base001; public class Test02 { public static void main(String[] args) { //第一次配置 //-Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC //第二次配置 //-Xms20m -Xmx20m -Xmn7m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC //第三次配置 //-XX:NewRatio=老年代/新生代 //-Xms20m -Xmx20m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC byte[] b = null; //連續向系統申請10MB空間 for(int i = 0 ; i <10; i ++){ b = new byte[1*1024*1024]; } } }
第一次配置
第二次配置
第三次配置
新生代和老年代的比例是1/2,新生代占一份,老生代占2份。
總結:不同的對分布情況,對系統執行會產生一定的影響,在實際工作中應該根據系統的特點作出合理的配置,基本策略:盡可能將對象預留在新生代,減少老年代的GC次數。
除了可以設置新生代的絕對大小(-Xmn),還可以使用(-XX:NewRatio)設置新生代和老年代的比例:-XX:NewRatio=老年代/新生代
堆溢出處理
在java程序的運行過程中,如果堆空間不足,則會拋出內存溢出的錯誤(Out Of Menory)OOM,一旦這類問題發生在生產環境,可能引起嚴重的業務中斷,java虛擬機提供了-XX:+HeapDumpOnOutOfMemoryError,使用該參數可以在內存溢出是導出整個堆信息,與之配合使用的還有參數,-XX:HeapDumpPath,可以設置到處堆得存放路徑。
內存分析工具:Memory Analyzer 1.5.0
地址:http://download.eclipse.org/mat/1.5/update-site/
package com.base001; import java.util.Vector; public class Test03 { public static void main(String[] args) { //-Xms2m -Xmx1m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/Test03.dump //堆內存溢出 Vector v = new Vector(); for(int i=0; i < 5; i ++){ v.add(new Byte[1*1024*1024]); } } }
添加參數
運行後的結果
存放到D盤下的異常文件。
棧配置
Java虛擬機提供了參數-Xss來制定線程的最大棧空間,整個參數也直接決定了函數課調用的最大深度。
package com.base001; public class Test04 { //-Xss1m //-Xss5m //棧調用深度 private static int count; public static void recursion(){ count++; recursion(); } public static void main(String[] args){ try { recursion(); } catch (Throwable t) { System.out.println("調用最大深入:" + count); t.printStackTrace(); } } }
添加參數
運行結果:
方法區
和java堆一樣,方法區是一塊所有線程共享的內存區域,它用於保存系統的類信息,方法區(永久區)可以保存多少信息可以對其進行配置,在默認情況下,-XX:MaxPermSize為64M,如果系統運行時產生大量的類,就需要設置一個相對合適的方法區,以免出現永久區內存溢出的問題。
-XX:PermSize=64M -XX:MaxPermSize=64M
JVM虛擬機(三):參數配置