java啓動參數共分爲三類html
-
),全部的JVM實現都必須實現這些參數的功能,並且向後兼容-X
),默認jvm實現這些參數的功能,可是並不保證全部jvm實現都知足,且不保證向後兼容-XX
),此類參數各個jvm實現會有所不一樣,未來可能會隨時取消,須要慎重使用能夠查看默認參數java
java -XX:+PrintCommandLineFlags -version
不要用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
這個參數會在控制檯打印全部類加載/卸載信息服務器
-XX:+TraceClassLoading -XX:+TraceClassUnloading
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof
-XX:OnOutOfMemoryError=/scripts/restart-myapp.sh
-XX:-CITime
-XX:-PrintCompilation
-Djava.net.preferIPv4Stack=true -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname={hostname} -Dcom.sun.management.jmxremote.port={port} -Dcom.sun.management.jmxremote.authenticate=false
JVM設置內存的單位默認是字節(不加單位的狀況下)。多線程
也能夠在大小後面增長單位,例如:oracle
-Xmn256m -Xmn262144k -Xmn268435456
-XX:NewSize=2G(也能夠是2M)
-XX:MaxNewSize=2G(也能夠是2M)
注意:-Xmn
優先級大於-XX:NewRatioapp
表示兩個Survivor和Edgen區的比,8表示兩個Survivor:Eden=2:8,即一個Survivor佔新生代的1/10。jvm
計算方式爲:jsp
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
#設置分配給永久生成的空間,若是超出該空間,則會觸發垃圾回收。此選項在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配置了多少內存並非說啓動後就會佔用多少物理內存,由於操做系統的內存分配是惰性的。對於已申請的內存雖然會分配地址空間,但並不會直接佔用物理內存,真正使用的時候纔會映射到實際的物理內存。
這裏說一下PermGen/Metaspace的GC,沒有查到官方資料說永久代的固定垃圾回收器,可是在stackoverflow上有人回答到:
全部垃圾回收器都會回收永久代,包括PS/CMS,但並非每一個GC週期都會清理永久代。
這個不用糾結,看GC日誌裏清理的信息便可。
最古老的,單線程,獨佔式,成熟,每次GC會STW,適合單CPU 服務器
Serial是一個新生代收集器,Serial Old是Serial收集器的的老年代版本
新生代和老年代都用串行收集器
-XX:+UseSerialGC
新生代使用ParallerGC,老年代使用Serial Old
-XX:+UseParallelGC
和Serial基本沒區別,惟一的區別:多線程,多CPU的,停頓時間比Serial少
新生代使用ParNew,老年代使用Serial Old
-XX:+UseParNewGC(在Java 8中已棄用,在Java 9中已刪除)
關注吞吐量的垃圾收集器,高吞吐量則能夠高效率地利用CPU時間,儘快完成程序的運算任務,主要適合在後臺運算而不須要太多交互的任務。
所謂吞吐量就是CPU用於運行用戶代碼的時間與CPU總消耗時間的比值,即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間),虛擬機總共運行了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。
Parallel Scavenge是一個新生代收集器,Parallel Old是Parallel Scavenge收集器的的老年代版本
新生代使用ParallerGC,老年代使用Parallel Old
-XX:+UseParallelGC #等價於 -XX:+UseParallelOldGC
CMS(Concurrent Mark Sweep),收集器是一種以獲取最短回收停頓時間爲目標的收集器,一個老年代垃圾回收器。目前很大一部分的Java應用集中在互聯網站或者B/S系統的服務端上,這類應用尤爲重視服務的響應速度,但願系統停頓時間最短,以給用戶帶來較好的體驗。CMS收集器就很是符合這類應用的需求。
新生代使用ParNew,老年代的用CMS
-XX:+UseConcMarkSweepGC
使用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 |
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 "
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:
PS:若是正在使用CMS或ParallelOld收集器,而且程序沒有遇到長時間的垃圾收集暫停,那麼就不須要升級到G1