簡介
java啓動參數共分爲三類
- 其一是標準參數(
-
),所有的JVM實現都必須實現這些參數的功能,而且向後兼容 - 其二是非標準參數(
-X
),默認jvm實現這些參數的功能,但是並不保證所有jvm實現都滿足,且不保證向後兼容 - 其三是非Stable參數(
-XX
),此類參數各個jvm實現會有所不同,將來可能會隨時取消,需要慎重使用
調試參數
打印啓動參數
可以查看默認參數
java -XX:+PrintCommandLineFlags -version
打印GC日誌
不要用XX:+UseGCLogFileRotation
,這個會丟失舊的日誌文件,而且重啓會覆蓋當前日誌文件:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/GCEASY/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M
應該用下面這個
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/GCEASY/gc-%t.log
打印ClassLoader日誌
這個參數會在控制檯打印所有類加載/卸載信息
-XX:+TraceClassLoading -XX:+TraceClassUnloading
OOM時Dump內存
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof
OOM時執行腳本(比如重啓)
-XX:OnOutOfMemoryError=/scripts/restart-myapp.sh
打印JIT時間
-XX:-CITime
方法被編譯時打印相關信息
-XX:-PrintCompilation
內存類
JVM設置內存的單位默認是字節(不加單位的情況下)。
也可以在大小後面增加單位,例如:
-Xmn256m
-Xmn262144k
-Xmn268435456
設置初始新生代大小
-XX:NewSize=2G(也可以是2M)
設置最大新生代大小
-XX:MaxNewSize=2G(也可以是2M)
注意:-Xmn
優先級大於-XX:NewRatio
設置Eden/Survivor比例
表示兩個Survivor和Edgen區的比,8表示兩個Survivor:Eden=2:8,即一個Survivor佔新生代的1/10。
計算方式爲:
Survivor Size(1) = Young Generation Size / (2+<SurvivorRatio)
Eden Size = Young Generation Size / (2+SurvivorRatio) * SurvivorRatio
配置:
-XX:SurvivorRatio=8
8也是默認的比例,不過這個比例在Parallel Scavenge(新生代並行回收器,JDK5以後的默認新生代回收器)回收器下是動態的,運行時會出現Eden/Survivor比例和配置的不同。
由於與吞吐量關係密切,Parallel Scavenge收集器也經常稱爲“吞吐量優先”收集器。除上述兩個參數之外,Parallel Scavenge收集器還有一個參數-XX:+UseAdaptiveSizePolicy值得關注。這是一個開關參數,當這個參數打開之後,就不需要手工指定新生代的大小(-Xmn)、Eden與Survivor區的比例(-XX:SurvivorRatio)、晉升老年代對象年齡(-XX:PretenureSizeThreshold)等細節參數了,虛擬機會根據當前系統的運行情況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或者最大的吞吐量,這種調節方式稱爲GC自適應的調節策略(GC Ergonomics)[插圖]。如果讀者對於收集器運作原來不太瞭解,手工優化存在困難的時候,使用Parallel Scavenge收集器配合自適應調節策略,把內存管理的調優任務交給虛擬機去完成將是一個不錯的選擇。只需要把基本的內存數據設置好(如-Xmx設置最大堆),然後使用MaxGCPauseMillis參數(更關注最大停頓時間)或GCTimeRatio (更關注吞吐量)參數給虛擬機設立一個優化目標,那具體細節參數的調節工作就由虛擬機完成了。自適應調節策略也是Parallel Scavenge收集器與ParNew收集器的一個重要區別。
https://docs.oracle.com/javas...
設置老年代大小
老年代大小無法直接設置,只能通過堆大小+分配比例進行調整
#設置新老一代大小之間的比率。默認值爲2。2表示New Size:Old Size=1:2,則新生代佔堆大小的1/3,老年代佔堆大小的2/3
-XX:NewRatio=2
新生代老年代大小計算方式爲:
New Size = Heap Size / NewRatio + 1
Old Size = (Heap Size / NewRatio + 1) * NewRatio
設置永久代(PermGen/MetaSpace)大小
#設置分配給永久生成的空間,如果超出該空間,則會觸發垃圾回收。此選項在JDK 8中已棄用,並由-XX:MetaspaceSize選項取代。
-XX:PermSize=size
#設置最大永久生成空間大小(以字節爲單位)。此選項在JDK 8中已棄用,並由-XX:MaxMetaspaceSize選項取代。
-XX:MaxPermSize=size
#設置分配的Metaspace的大小,Metaspace將在首次超過垃圾收集時觸發垃圾收集。 垃圾收集的閾值取決於使用的元數據量而增加或減少。 默認大小取決於平臺。
-XX:MetaspaceSize=size
#設置可以分配給Metaspace的最大本機內存。 默認情況下,大小不受限制。 應用程序的Metaspace量取決於應用程序本身,其他正在運行的應用程序以及系統上可用的內存量
-XX:MaxMetaspaceSize=size
初始大小和最大值的區別
初始值(比如-Xms
)爲JVM啓動是向操作系統申請的內存大小(malloc
),最大值(比如-Xmx
)表示,當使用的內存超過初始值後擴容的最大值
PS: JVM配置了多少內存並不是說啓動後就會佔用多少物理內存,因爲操作系統的內存分配是惰性的。對於已申請的內存雖然會分配地址空間,但並不會直接佔用物理內存,真正使用的時候纔會映射到實際的物理內存。
GC類
這裏說一下PermGen/Metaspace的GC,沒有查到官方資料說永久代的固定垃圾回收器,但是在stackoverflow上有人回答到:
所有垃圾回收器都會回收永久代,包括PS/CMS,但並不是每個GC週期都會清理永久代。
這個不用糾結,看GC日誌裏清理的信息即可。
Serial/Serial Old
最古老的,單線程,獨佔式,成熟,每次GC會STW,適合單CPU 服務器
Serial是一個新生代收集器,Serial Old是Serial收集器的的老年代版本
新生代和老年代都用串行收集器
-XX:+UseSerialGC
新生代使用ParallerGC,老年代使用Serial Old
-XX:+UseParallelGC
ParNew
和Serial基本沒區別,唯一的區別:多線程,多CPU的,停頓時間比Serial少
新生代使用ParNew,老年代使用Serial Old
-XX:+UseParNewGC(在Java 8中已棄用,在Java 9中已刪除)
Parallel Scavenge(ParallerGC)/Parallel Old
關注吞吐量的垃圾收集器,高吞吐量則可以高效率地利用CPU時間,儘快完成程序的運算任務,主要適合在後臺運算而不需要太多交互的任務。
所謂吞吐量就是CPU用於運行用戶代碼的時間與CPU總消耗時間的比值,即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間),虛擬機總共運行了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。
Parallel Scavenge是一個新生代收集器,Parallel Old是Parallel Scavenge收集器的的老年代版本
新生代使用ParallerGC,老年代使用Parallel Old
-XX:+UseParallelGC
#等價於
-XX:+UseParallelOldGC
Concurrent Mark Sweep (CMS)
CMS(Concurrent Mark Sweep),收集器是一種以獲取最短回收停頓時間爲目標的收集器,一個老年代垃圾回收器。目前很大一部分的Java應用集中在互聯網站或者B/S系統的服務端上,這類應用尤其重視服務的響應速度,希望系統停頓時間最短,以給用戶帶來較好的體驗。CMS收集器就非常符合這類應用的需求。
新生代使用ParNew,老年代的用CMS
-XX:+UseConcMarkSweepGC
G1
使用G1收集器
-XX:+UseG1GC
垃圾回收器的組合
命令 | 新生代回收器&算法 | 老年代回收器&算法 | 備註 |
---|---|---|---|
-XX:+UseSerialGC | Serial收集器 | Serial Old收集器 | |
-XX:+UseG1GC | G1收集器 | G1收集器 | |
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy | ParallerGC | Paraller Old | 新生代比例自適應調整 |
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseAdaptiveSizePolicy | ParallerGC | Paraller Old | 新生代比例不自動調整 |
-XX:+UseParNewGC | ParNew | Serial Old | Java8廢棄,Java9移除 |
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC | ParNew | CMS | |
-XX:+UseConcMarkSweepGC -XX:-UseParNewGC | Serial | CMS | Java8廢棄,Java9移除 |
下面是一些缺省的寫法
命令 | 等同於上表 |
---|---|
-XX:+UseParallelGC | -XX:+UseParallelGC -XX:+UseParallelOldGC |
-XX:+UseParallelOldGC | -XX:+UseParallelGC -XX:+UseParallelOldGC |
-Xincgc (Java8廢棄,Java9移除) | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC |
-XX:+UseConcMarkSweepGC | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC |
常用JVM參數組合
JDK7
JAVA_MEM_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
JAVA_DEBUG_OPTS=" -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/GCEASY/gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof -XX:OnOutOfMemoryError=/scripts/restart-myapp.sh "
JDK8
JAVA_MEM_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -XX:MetaspaceSize=256m -Xss1024m -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
JAVA_DEBUG_OPTS=" -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/GCEASY/gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof -XX:OnOutOfMemoryError=/scripts/restart-myapp.sh "
關於G1,雖然說JDK8中已經支持G1了,但是並不是說一定需要。
G1的重要特點是爲用戶的應用程序的提供一個低GC延時和大內存GC的解決方案,適用於大內存場景(官方推薦堆6G以上)
如果程序正在使用CMS或ParallelOld垃圾回收器,並且具有一個或多個以下特徵,那麼則可以考慮升級爲G1:
- Full GC持續時間太長或太頻繁
- 對象分配率或年輕代升級老年代很頻繁
- 垃圾收集時間或壓縮暫停(超過0.5至1秒)時間過長
PS:如果正在使用CMS或ParallelOld收集器,並且程序沒有遇到長時間的垃圾收集暫停,那麼就不需要升級到G1
參考
- 《深入理解Java虛擬機:JVM高級特性與實戰(第2版)》 - 周志明[著]
- http://www.fasterj.com/articl...
- https://www.oracle.com/techne...
- https://www.oracle.com/techne...
- https://docs.oracle.com/javas...