話很少說,今天就分析一下一些經常使用的Java虛擬機的參數設置,以及如何更好的使用!html
首先想說的是其實這些參數咱們並非陌生的,在平時的開發和使用中常常都會遇到,只是在平時缺乏一個比較系統的總結,因此,對這些參數感受是很陌生的,因此,經過這篇文章的總結,我相信你必定都會對這些參數熟稔於心,作作心中有數。java
在Java虛擬機的參數中,其實能夠把這些參數分爲三類,固然,這是針對JDK1.6來講的,若是對於JDK1.8,那麼就不是這麼分類的了,可是,因爲這兩個版本不少經常使用的參數的差異是不大的,因此這篇文章就先介紹JDK1.6的VM參數。算法
主要能夠分爲如下三類:windows
標準參數(-)
,全部的JVM實現都必須實現這些參數的功能,並且向後兼容。非標準參數(-X)
,默認JVM實現這些參數的功能,可是並不保證全部JVM實現都知足,且不保證向後兼容。非Stable參數(-XX)
,此類參數各個JVM實現會有所不一樣,未來可能會隨時取消,須要慎重使用。雖然是這麼分類的,實際上呢,非標準參數和非穩定的參數實際的使用中仍是用的很是的多的,在後面的文章的介紹中你就會發現。服務器
這一類參數能夠說是咱們剛剛開始Java是就用的很是多的參數了,好比java -version
、java -jar
等等,咱們在CMD中輸入java -help
就能夠得到Java當前版本的全部標準參數了。微信
如上圖就是JDK1.8的全部標準參數了,下面咱們將介紹一些咱們會用的比較多的參數。網絡
以client模式啓動JVM,這種方式啓動速度快,但運行時性能和內存管理效率不高,適合客戶端程序或者開發調試。併發
以server模式啓動JVM,與client狀況剛好相反。適合生產環境,適用於服務器。64位的JVM自動以server模式啓動。oracle
通知JVM類搜索路徑。若是指定了-classpath
,則JVM就忽略CLASSPATH
中指定的路徑。各路徑之間以分號隔開。若是-classpath
和CLASSPATH
都沒有指定,則JVM從當前路徑尋找class。jvm
JVM搜索路徑的順序:
1.先搜索JVM自帶的jar或zip包。
Bootstrap,搜索路徑能夠用System.getProperty("sun.boot.class.path")
得到;
2.搜索JRE_HOME/lib/ext
下的jar包。
Extension,搜索路徑能夠用System.getProperty("java.ext.dirs")
得到;
3.搜索用戶自定義目錄,順序爲:當前目錄(.),CLASSPATH,-cp。
搜索路徑用System.getProperty("java.class.path")
得到。
System.out.println(System.getProperty("sun.boot.class.path")); System.out.println(System.getProperty("java.ext.dirs")); System.out.println(System.getProperty("java.class.path"));
如上就是我電腦的JVM的路徑。
定義系統的全局屬性值,如配置文件地址等,若是value有空格,則須要使用雙引號。
另外用System.getProperty("hello")
能夠得到這些定義的屬性值,在代碼中也能夠用System.setProperty("hello","world")
的形式來定義屬性。
如鍵值對設置爲hello=world。
System.out.println(System.getProperty("hello"));
運行結果就是:
查詢GC問題最經常使用的命令之一,參數以下:
-verbose:class
輸出JVM載入類的相關信息,當JVM報告說找不到類或者類衝突時可此進行診斷。
-verbose:gc
輸出每次GC的相關狀況。
-verbose:jni
輸出native方法調用的相關狀況,通常用於診斷jni調用錯誤信息。
另外,控制檯輸出GC信息還可使用以下命令:
在JVM的啓動參數中加入-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime
,按照參數的順序分別輸出GC的簡要信息,GC的詳細信息、GC的時間信息及GC形成的應用暫停的時間。
非標註的參數主要是關於Java內存區域的設置參數,因此在看這些參數以前,應該先查看Java內存區域的基礎知識,能夠查看這篇文章:深刻理解Java虛擬機-Java內存區域透徹分析。
非標準參數實在標準參數的基礎上的一些擴充參數,能夠輸入java -X
,得到當前JVM支持的非標準參數。
從圖片中能夠看出來,這些非標準的參數其實很少的,下面咱們再 講解一些比較經常使用的參數。
新生代內存大小的最大值,包括E區和兩個S區的總和。設置方法:-Xmn512m、-Xmn2g
。
初始堆的大小,也是堆大小的最小值,默認值是總共的物理內存/64(且小於1G)。默認狀況下,當堆中可用內存小於40%,堆內存會開始增長,一直增長到-Xmx的大小。
堆的最大值,默認值是總共的物理內存/64(且小於1G),默認狀況下,當堆中可用內存大於70%,堆內存會開始減小,一直減少到-Xms的大小。
所以,爲了不這種浮動,因此在設置-Xms
和-Xmx
參數時,通常會設置成同樣的,可以提升性能。
另外,官方默認的配置爲年老代大小:年輕代大小=2:1左右,使用-XX:NewRatio
能夠設置年老代和年輕代之比,例如,-XX:NewRatio=4
,表示年老代:年輕代=4:1
參數實例
設置-Xms
、-Xmn
和-Xmx
參數分別爲-Xms512m -Xmx512m -Xmn128m
。同時設置新生代和老生代之比爲1:4,E:S0:S1=8:1:1。
** * @ClassName MethodTest * @Description vm參數設置:-Xms512m -Xmx512m -Xmn128m -XX:NewRatio=4 -XX:SurvivorRatio=8 * @Author 歐陽思海 * @Date 2019/11/25 20:06 * @Version 1.0 **/ public class MethodTest { public static void main(String[] args) { List<String> list = new ArrayList<String>(); long i = 0; while (i < 1000000000) { System.out.println(i); list.add(String.valueOf(i++).intern()); } } }
運行以後,用VisualVM查看相關信息是否正確。
當咱們沒有設置-XX:NewRatio=4 -XX:SurvivorRatio=8
時,使用官方默認的狀況以下:
上圖能夠看出,新生代(Eden Space + Survivor 0 + Survivor 1):老年代(Old Gen)≈ 1:2。
當咱們設置了-XX:NewRatio=4 -XX:SurvivorRatio=8
時,狀況以下:
變成了新生代(Eden Space + Survivor 0 + Survivor 1):老年代(Old Gen)≈ 1:4,Eden Space:Survivor 0: Survivor 1 = 8:1:1。
從上圖可知,堆的信息是正確的。
設置每一個線程的棧內存,默認1M,通常來講是不須要改的。
跟蹤正運行的程序,並將跟蹤數據在標準輸出輸出;適合於開發環境調試。
禁用類垃圾收集,關閉針對class的gc功能;由於其阻止內存回收,因此可能會致使OutOfMemoryError錯誤,慎用。
開啓增量gc(默認爲關閉);這有助於減小長時間GC時應用程序出現的停頓;但因爲可能和應用程序併發執行,因此會下降CPU對應用的處理能力。
與-verbose:gc
功能相似,只是將每次GC事件的相關狀況記錄到一個文件中,文件的位置最好在本地,以免網絡的潛在問題。
若與verbose命令同時出如今命令行中,則以-Xloggc爲準。
在解釋模式(interpreted mode)下,-Xint
標記會強制JVM執行全部的字節碼,這會下降運行速度,一般低10倍或更多。
-Xcomp參數與它(-Xint)正好相反,JVM在第一次使用時會把全部的字節碼編譯成本地代碼,從而帶來最大程度的優化。
然而,不少應用在使用-Xcomp
也會有一些性能損失,固然這比使用-Xint損失的少,緣由是-xcomp
沒有讓JVM啓用JIT
編譯器的所有功能。JIT編譯器能夠對是否須要編譯作判斷,若是全部代碼都進行編譯的話,對於一些只執行一次的代碼就沒有意義了。
-Xmixed
是混合模式,這是JVM默認的模式,也是推薦使用的模式。將解釋模式與編譯模式進行混合使用,由JVM本身決定。
這類參數你一看官網覺得不能使用呢,官網給你的建議就是這些參數不穩定,慎用,其實這主要的緣由仍是由於每一個公司的實現都是不同的,因此就是致使不穩定。可是呢,在實際的使用中倒是很是的多的,並且這部分的參數很重要。
這些參數大體能夠分爲三類:
下面仍是先羅列一些比較經常使用的參數,其實,這些文章不少了,這裏主要仍是作一個總結,之後本身看文章的時候比較方便,若是有同行看到了文章,你能夠參考參考,仍是頗有幫助的。
另外,選取其中的一些參數作一些例子來解釋,這樣也可以更加的形象。
注意:如下參數都是JDK1.7及如下可使用。
參數及其默認值 | 描述 |
---|---|
-XX:LargePageSizeInBytes=4m | 設置用於Java堆的大頁面尺寸 |
-XX:MaxHeapFreeRatio=70 | GC後java堆中空閒量佔的最大比例 |
-XX:MinHeapFreeRatio=40 | GC後java堆中空閒量佔的最小比例 |
-XX:MaxNewSize=size | 新生成對象能佔用內存的最大值 |
-XX:MaxPermSize=64m | 老生代對象能佔用內存的最大值 |
-XX:NewRatio=2 | 新生代內存容量與老生代內存容量的比例 |
-XX:NewSize=2.125m | 新生代對象生成時佔用內存的默認值 |
-XX:ReservedCodeCacheSize=32m | 保留代碼佔用的內存容量 |
-XX:ThreadStackSize=512 | 設置線程棧大小,若爲0則使用系統默認值 |
-XX:+UseLargePages | 使用大頁面內存 |
參數及其默認值 | 描述 |
---|---|
-XX:+ScavengeBeforeFullGC | 新生代GC優先於Full GC執行 |
-XX:+UseGCOverheadLimit | 在拋出OOM以前限制jvm耗費在GC上的時間比例 |
-XX:-UseParNewGC | 打開此開關,使用ParNew+Serial Old 收集器 |
-XX:-UseConcMarkSweepGC | 使用ParNew+CMS+Serial Old 收集器對老生代採用併發標記交換算法進行GC |
-XX:-UseParallelGC | 啓用並行GC,使用ParallelScavenge+Serial Old 收集器 |
-XX:-UseParallelOldGC | 對Full GC啓用並行,當-XX:-UseParallelGC 啓用時該項自動啓用,ParallelScavenge+Parallel Old 收集器 |
-XX:-UseSerialGC | 啓用串行GC |
-XX:+UseG1GC | 使用垃圾優先(G1)收集器 |
-XX:SurvivorRatio=n | Eden區域與Survivor區域大小之比。預設值爲8 |
-XX:PretenureSizeThreshold=n | 直接晉升到老年代的對象大小,設置這個參數以後,大於這個參數的對象直接進入到老年代分配 |
-XX:MaxTenuringThreshold=n | 晉升到老年代的對象年齡,每一個對象在堅持過一次Minor GC以後,年齡加1,當超過這個值以後就進入老年代。預設值爲15 |
-XX:+UseAdaptiveSizePolicy | 動態調整Java堆中各個區域的大小以及進入老年代的年齡 |
-XX:ParallelGCThreads=n | 設置並行收集器收集時使用的CPU數。並行收集線程數 |
-XX:MaxGCPauseMillis=n | 設置並行收集最大暫停時間 |
-XX:GCTimeRatio=n | 設置垃圾回收時間佔程序運行時間的百分比。公式爲1/(1+N) |
-XX:+UseThreadPriorities | 啓用本地線程優先級 |
-XX:-DisableExplicitGC | 禁止調用System.gc() ;但jvm的gc仍然有效 |
-XX:+MaxFDLimit | 最大化文件描述符的數量限制 |
前面6個參數都是關於垃圾收集器的行爲參數,也是常常會用到的參數。
參數及其默認值 | 描述 |
---|---|
-XX:-CITime | 打印消耗在JIT編譯的時間 |
-XX:ErrorFile=./hs_err_pid<pid>.log | 保存錯誤日誌或者數據到文件中 |
-XX:HeapDumpPath=./java_pid<pid>.hprof | 指定導出堆信息時的路徑或文件名 |
-XX:-HeapDumpOnOutOfMemoryError | 當首次遭遇OOM時導出此時堆中相關信息 |
-XX:OnError="<cmd args>;<cmd args>" | 出現致命ERROR以後運行自定義命令 |
-XX:OnOutOfMemoryError="<cmd args>;<cmd args>" | 當首次遭遇OOM時執行自定義命令 |
-XX:-PrintClassHistogram | 遇到Ctrl-Break後打印類實例的柱狀信息,與jmap -histo 功能相同 |
-XX:-PrintConcurrentLocks | 遇到Ctrl-Break後打印併發鎖的相關信息,與jstack -l 功能相同 |
-XX:-PrintCommandLineFlags | 打印在命令行中出現過的標記 |
-XX:-PrintCompilation | 當一個方法被編譯時打印相關信息 |
-XX:-PrintGC | 每次GC時打印相關信息 |
-XX:-PrintGCDetails | 每次GC時打印詳細信息 |
-XX:-PrintGCTimeStamps | 打印每次GC的時間戳 |
-XX:-TraceClassLoading | 跟蹤類的加載信息 |
-XX:-TraceClassLoadingPreorder | 跟蹤被引用到的全部類的加載信息 |
-XX:-TraceClassResolution | 跟蹤常量池 |
-XX:-TraceClassUnloading | 跟蹤類的卸載信息 |
-XX:-TraceLoaderConstraints | 跟蹤類加載器約束的相關信息 |
因爲考慮到如今JDK8用的很是的普遍,因此,接下來總結一些JDK8會使用到的參數。
查看這篇JDK8的參數文章你會發現,標準參數和非標準參數JDK8的差異並非很大,若是有其餘的參數須要使用,能夠查看上面這篇文章。
Java虛擬機深刻理解系列所有文章更新中...
一、 原創不易,老鐵,文章須要你的 點贊 讓更多的人看到,但願可以幫助到你們!二、文章有不當之處,歡迎指正,若是喜歡微信閱讀,你也能夠關注個人微信公衆號:
好好學java
,公衆號已有 6W 粉絲,回覆:1024,獲取公衆號的大禮包,公衆號長期發佈 Java 優質系列文章,關注咱們必定會讓你收穫不少!