您好,登錄后才能下訂單哦!
這篇文章主要介紹“常用的java虛擬機參數有哪些”,在日常操作中,相信很多人在常用的java虛擬機參數有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”常用的java虛擬機參數有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
-XX:+PrintGC
(在jdk9、jdk10中建議使用-Xlog:gc
)最簡單的一個GC參數是-XX:+PrintGC
(在jdk9、jdk10中建議使用-Xlog:gc
),使用這個參數啟動jvm后,只要遇到GC,就會打印日志。
[GC 4893K->377K(15872K), 0.0006926 secs]
一行記錄表示進行了一次GC,該GC記錄顯示,在GC前,堆空間使用量約為4MB,在GC后,堆空間使用量為377KB,當前堆空間的總和約為16MB(15872K)。最后顯示的是本次GC所花的時間。
jdk9、jdk10默認使用G1作為垃圾回收器,使用參數-Xlog:gc
來打印GC日志,如下圖所示:
[0.012s][info][gc] Using G1 [0.107s][info][gc] GC(0) Pause Full (System.gc()) 16M->7M(34M) 23.511ms
該日志顯示,一共進行了一次GC,在GC前,堆空間使用量為16MB,在GC后,堆空間使用量為7MB,當前堆空間總和為34MB。最后,顯示的是本次GC所花的時間,為23.511ms。
-XX+PrintGCDetails
(在jdk9、jdk10中建議使用-Xlog:gc*
)如果需要更加詳細的信息,可以使用-XX:+PrintGCDetails
(在jdk9、jdk10中建議使用-Xlog:gc*
)參數。該參數會使虛擬機在退出前打印堆的詳細信息,詳細信息描述了當前堆的各個區間的使用情況。
-XX:+PrintHeapAtGc
(從jdk9起,已刪除該參數)如果需要更全面的堆信息,還可以使用-XX:+PrintHeapAtGc
(考慮到兼容性,從jdk9起,已刪除該參數,查看堆信息可以使用Visual VM
)。它會在每次GC前、后分別打印堆的信息,就如同-XX+PrintGCDetails
的最后輸出一樣。
由于GC會引起應用程序停頓,因此還需要特別關注應用程序的執行時間和停頓時間。使用參數-XX:+PrintGCApplicationConcurrentTime
可以打印應用程序的執行時間,使用參數-XX:+PrintGCApplicationStoppedTime
可以打印應用程序由于GC而產生的停頓時間。
如果想跟蹤系統內的軟引用、弱引用、虛引用和Finallize隊列,可以打開-XX:+PrintReferenceGC
(考慮到兼容性,從jdk9開始已經刪除此參數,查看堆信息可以使用Visual VM
)開關。
默認情況下,GC的日志會在控制臺中輸出,這不便后續分析和定位問題。所以虛擬機允許將GC日志以文件的形式輸出,可以使用參數-Xloggc
指定。
比如,使用參數-Xloggc:log/gc.log
(在jdk9、jdk10中建議使用-Xlog:gc:/log/gc.log
)啟動虛擬機,可以在當前目錄的log文件夾下的gc.log文件中記錄所有的GC日志。
java程序的運行離不開類的加載,為了更好地理解程序如何執行,有時候需要知道系統加載了哪些類。
跟蹤類的加載與卸載: 可以使用參數-verbose:class
跟蹤類的加載與卸載.
單獨跟蹤類的加載:可以使用參數-XX:+TraceClassLoading
(在jdk9、jdk10中建議使用-Xlog:class+load=info
,跟jdk8中的參數-XX:+TraceClassLoading
效果相同)單獨跟蹤類的加載。
單獨跟蹤類的卸載:可以使用參數-XX:+TraceClassUnloading
(在jdk9、jdk10中建議使用-Xlog:class+unload=info
,跟jdk8中的參數-XX:+TraceClassUnloading
效果相同)跟蹤類的卸載。
-XX:+PrintClassHistogram
: 該參數表示遇到 Ctrl-Break
后打印類實例的柱狀信息,與 jmap -histo
功能相同
由于目前的java虛擬機支持眾多的可配參數,不同的參數可能對系統的執行效果有較大的影響,因此有必要明確當前系統的實際運行參數。虛擬機提供了一些手段來幫助研發人員獲得這些參數。
-XX:PrintVMOptions
:可以在程序運行時打印虛擬機接收到的命令行顯式參數。
-XX:PrintCommandLineFlags
:可以打錢傳遞給虛擬機的顯示和隱式參數,隱式參數未必是通過命令行直接給出的,它可能是在虛擬機啟動時自行設置的。
-XX:+PrintFlagsFinal
:會打印所有的系統參數的值,開啟這個參數后,虛擬機可能會產生500多行輸出,每一行為一個配置參數及其當前取值。
初始堆與最大堆分別使用-Xms
、-Xmx
來指定,如指定初始堆大小為5MB、最大堆大小為20MB:-Xms5m
、-Xmx20m
。在實際生產中,為了減少程序運行時垃圾回收的次數,一般直接將初始堆-Xms
與最大堆-Xmx
設置為相等。
參數-Xmn
可以用于設置新生代的大小,設置一個較大的新生代減少老年代的大小,這個參數對系統性能及GC行為有很大的影響。** 新生代的大小一般設置為整個堆空間的 1/3
到 1/4
**.
參數-XX:SurvivorRatio
用來設置新生代中eden
區和from/to
區的比例,它的含義如下:
-XX:SurvivorRatio = eden/form = eden/to
示例:
public class Demo02 { public static void main(String[] args) { byte[] b = null; for(int i = 0; i < 10; i++) { b = new byte[2 * 1024 * 1024]; } } }
-Xmx40m -Xms40m -Xmn2m -XX:SurvivorRatio=2 -XX:+PrintGCDetails
運行[GC (Allocation Failure) [PSYoungGen: 1024K->432K(1536K)] 1024K->432K(40448K), 0.0015289 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap PSYoungGen total 1536K, used 885K [0x00000007bfe00000, 0x00000007c0000000, 0x00000007c0000000) eden space 1024K, 44% used [0x00000007bfe00000,0x00000007bfe716b0,0x00000007bff00000) from space 512K, 84% used [0x00000007bff00000,0x00000007bff6c010,0x00000007bff80000) to space 512K, 0% used [0x00000007bff80000,0x00000007bff80000,0x00000007c0000000) ParOldGen total 38912K, used 20480K [0x00000007bd800000, 0x00000007bfe00000, 0x00000007bfe00000) object space 38912K, 52% used [0x00000007bd800000,0x00000007bec000a0,0x00000007bfe00000) Metaspace used 3066K, capacity 4496K, committed 4864K, reserved 1056768K class space used 337K, capacity 388K, committed 512K, reserved 1048576K
這里的 eden區
與 from區
的比值為2:1,故 eden區
為1024kb,總可用新生代大小為1024kb + 512kb = 1536kb
,新生代總大為1024kb+512kb+512kb=2048kb=2mb
.
由于eden區無法容納任何程序中分配的2MB的數組,故觸發了一次新生代gc,對eden區進行了部分回收。同時,這個偏小的新生代無法為2MB數組預留空間,故所有的數組都分配在老年代,老年代最終占用20480K空間。
-Xmx40m -Xms40m -Xmn14m -XX:SurvivorRatio=2 -XX:+PrintGCDetails
運行[GC (Allocation Failure) [PSYoungGen: 5477K->2560K(10752K)] 5477K->2568K(37376K), 0.0016892 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 8915K->2592K(10752K)] 8923K->2600K(37376K), 0.0015561 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 9050K->2544K(10752K)] 9058K->2552K(37376K), 0.0009707 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] Heap PSYoungGen total 10752K, used 6871K [0x00000007bf200000, 0x00000007c0000000, 0x00000007c0000000) eden space 7168K, 60% used [0x00000007bf200000,0x00000007bf639d28,0x00000007bf900000) from space 3584K, 70% used [0x00000007bf900000,0x00000007bfb7c020,0x00000007bfc80000) to space 3584K, 0% used [0x00000007bfc80000,0x00000007bfc80000,0x00000007c0000000) ParOldGen total 26624K, used 8K [0x00000007bd800000, 0x00000007bf200000, 0x00000007bf200000) object space 26624K, 0% used [0x00000007bd800000,0x00000007bd802000,0x00000007bf200000) Metaspace used 2970K, capacity 4496K, committed 4864K, reserved 1056768K class space used 328K, capacity 388K, committed 512K, reserved 1048576K
本次將新生代擴大為14MB(7168k+3584K+3584k=14336K
),在這個參數下,由于eden區有足夠的空間,因此所有的數組都分配在eden區。但eden區并不足以預留10MB的空間,故在程序運行期間出現了3次新生代gc.由于每申請一次空間,同時也廢棄了上一次申請的空間(上一次申請的內存失去了引進),故在新生代gc中,有效回收了這些失效的內存。最終結果是:所有的內存分配都在新生代進行,通過gc保證了新生代有足夠的空間,而老年代沒有為這些數組預留任何空間,只是在gc過程中,部分新生代對象晉升到老年代。
-Xmx40m -Xms40m -Xmn30m -XX:SurvivorRatio=8 -XX:+PrintGCDetails
運行Heap PSYoungGen total 27648K, used 23437K [0x00000007be200000, 0x00000007c0000000, 0x00000007c0000000) eden space 24576K, 95% used [0x00000007be200000,0x00000007bf8e3510,0x00000007bfa00000) from space 3072K, 0% used [0x00000007bfd00000,0x00000007bfd00000,0x00000007c0000000) to space 3072K, 0% used [0x00000007bfa00000,0x00000007bfa00000,0x00000007bfd00000) ParOldGen total 10240K, used 0K [0x00000007bd800000, 0x00000007be200000, 0x00000007be200000) object space 10240K, 0% used [0x00000007bd800000,0x00000007bd800000,0x00000007be200000) Metaspace used 3064K, capacity 4496K, committed 4864K, reserved 1056768K class space used 336K, capacity 388K, committed 512K, reserved 1048576K
在這次執行中,由于新生代使用30MB空間,其中eden占24MB(30MB / 10 * 8
),完全滿足10MB數組的分配,因此所有的分配行為都在eden區直接進行,且沒有觸發任何GC行為。因此,from/to和老年代的使用率都為0
由此可見,不同的堆分布情況對系統會產生一定的影響。在實際工作中,應該根據系統的特點做合理的設置,基本策略是:盡可能將對象預留在新生代,減少老年代gc的次數。
-Xmx40m -Xms40m -XX:NewRatio=2 -XX:+PrintGCDetails
除了可以使用參數 -Xmn
指定新生代的絕對大小,還可以使用參數 -XX:NewRatio
來設置新生代和老年代的比例,如下所示:
-XX:NewRatio=老年代/新生代
本例中,設置的老年代與新生代的比例為2:1.運行結果如下:
[GC (Allocation Failure) [PSYoungGen: 10075K->496K(11776K)] 10075K->2552K(39424K), 0.0019760 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 8989K->560K(11776K)] 11045K->4672K(39424K), 0.0015192 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] Heap PSYoungGen total 11776K, used 5144K [0x00000007bf300000, 0x00000007c0000000, 0x00000007c0000000) eden space 10240K, 44% used [0x00000007bf300000,0x00000007bf77a088,0x00000007bfd00000) from space 1536K, 36% used [0x00000007bfe80000,0x00000007bff0c010,0x00000007c0000000) to space 1536K, 0% used [0x00000007bfd00000,0x00000007bfd00000,0x00000007bfe80000) ParOldGen total 27648K, used 4112K [0x00000007bd800000, 0x00000007bf300000, 0x00000007bf300000) object space 27648K, 14% used [0x00000007bd800000,0x00000007bdc04020,0x00000007bf300000) Metaspace used 3044K, capacity 4496K, committed 4864K, reserved 1056768K class space used 333K, capacity 388K, committed 512K, reserved 1048576K
此時,堆的大小為40MB,新生代和老年代的比為1:2,故新生代大小為40*(1/3)=14MB
(其中,eden約為14MB*(8/10)=11.2MB
,from/to大小為14*(1/10)=1.4MB
),老年代約為26MB。由于在新生代GC時,from/to空間不足以容納任何一個2MB數組,影響了新生代的正常回收,故在新生代回收時需要老年代進行空間擔保。這導致兩個2MB數組進入老年代(在新生代gc時,尚有1MB數組幸存,理應進入from/to區,而from/to區只有1.4MB,不足以容納)。
在java程序的運行過程中,如果堆空間不足,則有可能會拋出內存溢出,簡稱OOM:
public class Demo03 { public static void main(String[] args) { Vector vector = new Vector(); for(int i = 0; i < 25; i++) { vector.add(new byte[1*1024*1024]); } } }
使用參數 -Xmx20m -Xms20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./dump.log
啟動,結果如下:
java.lang.OutOfMemoryError: Java heap space Dumping heap to ./dump.log ... Heap dump file created [19887142 bytes in 0.015 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at jvm.chapter03.Demo03.main(Demo03.java:16)
可以看到,虛擬機將當前的堆棧信息導出,并保存到dump.out文件中。
除了在發生OOM時可以導出堆信息,虛擬機還允許在發生錯誤時執行一個腳本文件。該文件可以用于崩潰程序的自救、報警或通知,也可以幫助開發人員獲得更多的系統信息,如完整的線程保存。
在 jdk 1.6
和 jdk 1.7
等版本中,可以使用 -XX:PermSize
和 -XX:MaxPermSize
配置永久區大小 。其中,-XX:PermSize
表示初始的永久區大小,-XX:MaxPermSize
表示最大永久區大小。
從 jdk1.8
開始,永久區被徹底移除,使用了新的元數據區存放類的元數據。在默認情況下,元數據區只受系統可用內存的限制,但依然可以使用參數 -MaxMetaspaceSize
指定永久區的最大可用值。
在NIO被廣泛使用后,直接內存的使用變得非常普遍,直接內存跳過了Java堆,使用Java程序可以直接訪問原生堆空間。因此,從一定程度上加快了內存空間的訪問速度。
最大可以直接內存可以使用參數 -XX:MaxDirectMemorySize
設置。如果不設置,默認值為最大堆空間,即-Xmx
的值。當直接內存使用量達到 -XX:MaxDirectMemorySize
時,就會觸發垃圾回收,如果垃圾回收不能有效釋放足夠的空間,直接內存溢出依然會引起系統的OOM.
直接內存的訪問速度比堆內存快;在申請空間時,堆內存的速度遠遠快于直接內存。因此,直接內存適合申請次數較少、訪問頻繁的場合。如果需要頻繁申請內存空間,則并不適合使用直接內存。
目前,java虛擬機支持 Client
和 Server
兩種運行模式,使用參數 -client
可以指定使用 Client模式
,使用參數 -server
可以指定使用 Server模式
。在默認情況下,虛擬機會根據當前計算機系統環境自動選擇運行模式。使用-version
參數可以查看當前模式:
java version "1.8.0_201" Java(TM) SE Runtime Environment (build 1.8.0_201-b09) Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
server模式
啟動較client模式
慢,因為server模式
會嘗試收集更多的系統性能信息,使用更復雜的算法對程序進行優化。因此,當系統完全啟動并進入運行穩定期后,server模式
的執行速度會遠遠快于client模式``。對于長期運行的系統更適合server模式
,但對于用戶界面程序而言,運行時間不長,又追求啟動速度,更適合client模式
。
虛擬機在server模式
和client模式
下的各種參數可能會有很大不同,可以使用-XX:+PrintFlagsFinal
查看參數的默認值,這里以查看 CompileThreshold
與 MaxHeapSize
為例,示例如下:
對于 client模式
:
$ java -XX:+PrintFlagsFinal -client -version | grep -E 'CompileThreshold | MaxHeapSize' intx CompileThreshold = 10000 {pd product} uintx MaxHeapSize := 4294967296 {product} intx Tier2CompileThreshold = 0 {product} intx Tier3CompileThreshold = 2000 {product} intx Tier4CompileThreshold = 15000 {product} java version "1.8.0_201" Java(TM) SE Runtime Environment (build 1.8.0_201-b09) Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
對于 server模式
:
$ java -XX:+PrintFlagsFinal -server -version | grep -E 'CompileThreshold | MaxHeapSize' intx CompileThreshold = 10000 {pd product} uintx MaxHeapSize := 4294967296 {product} intx Tier2CompileThreshold = 0 {product} intx Tier3CompileThreshold = 2000 {product} intx Tier4CompileThreshold = 15000 {product} java version "1.8.0_201" Java(TM) SE Runtime Environment (build 1.8.0_201-b09) Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
到此,關于“常用的java虛擬機參數有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。