對象優(yōu)先分配到Eden區(qū)
/**
* -XX:+PrintGCDetails 打印GC詳情信息
* -XX:+PrintGC 打印GC信息
*/
public class TestPolicy1 {
private static final int _1MB = 1024 * 1024;
public static void testAllocation() {
byte[] allocation1, allocation2, allocation3, allocation4;
allocation1 = new byte[2 * _1MB];
allocation2 = new byte[2 * _1MB];
allocation3 = new byte[2 * _1MB];
allocation4 = new byte[4 * _1MB];
}
public static void main(String[] args) {
testAllocation();
}
}
大對象直接進(jìn)入老年代
/**
* -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
* -XX:PretenureSizeThreshold=3145728 // 設(shè)置對象直接進(jìn)入老年代的閾值。對SerialGC和ParNew起作用
*/
public class TestPolicy2 {
private static final int _1MB = 1024 * 1024;
/**
* VM參數(shù):-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
* -XX:PretenureSizeThreshold=3145728胞谭。默認(rèn)值是0
*/
public static void testPretenureSizeThreshold() {
byte[] allocation;
// 直接分配在老年代中
allocation = new byte[4 * _1MB];
}
public static void main(String[] args) {
testPretenureSizeThreshold();
}
}
長期存活的對象會進(jìn)入老年代
public class TestPolicy3 {
private static final int _1MB = 1024 * 1024;
/**
* VM參數(shù):-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90
* -XX:+PrintGCDetails
* -XX:MaxTenuringThreshold=1
* -XX:+PrintTenuringDistribution
* Jdk 1.7.0_46
*/
public static void testTenuringThreshold() throws InterruptedException {
byte[] allocation1, allocation2, allocation3;
allocation1 = new byte[_1MB / 4];
//什么時(shí)候進(jìn)入老年代取決于XX:MaxTenuringThreshold設(shè)置
allocation2 = new byte[4 * _1MB];
allocation3 = new byte[4 * _1MB];
System.out.println("=============");
allocation3 = null;
allocation3 = new byte[4 * _1MB];
System.out.println("=============");
}
public static void main(String[] args) throws InterruptedException {
testTenuringThreshold();
}
}
動態(tài)年齡判斷
如果在Survivor空間中相同年齡的所有對象大小的總和大于Survivor空間的一半同廉,年齡大于或者等于平均年齡的對象直接進(jìn)入老年代羡洛。
空間擔(dān)保
在發(fā)生Minor GC之前,虛擬機(jī)會先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象總空間踊餐,如果這個條件成立景醇,那么Minor GC可以確保是安全的。如果不成立吝岭,則虛擬機(jī)會查看HandlePromotionFailure設(shè)置值是否允許擔(dān)保失敗三痰。
如果允許,那么會繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小窜管,如果大于散劫,將嘗試著進(jìn)行一次Minor GC,盡管這次Minor GC是有風(fēng)險(xiǎn)的幕帆;如果小于获搏,或者HandlePromotionFailure設(shè)置不允許冒險(xiǎn),那這時(shí)也要改為進(jìn)行一次Full GC蜓肆。
關(guān)于GC清理
MinorGC用于清理新生代颜凯,MajorGC清理老年代。FullGC清理新生代+老年代(方法區(qū))
MinorGC觸發(fā)條件:當(dāng)新生代無法給新對象分配空間時(shí)仗扬。如:Eden區(qū)滿了症概。
MajorGC觸發(fā)條件:老年代沒有空間。經(jīng)歷一次MinorGC
FullGC觸發(fā)條件:
- System.gc
- 老年代空間不足
- 方法區(qū)空間不足
- 經(jīng)過MinorGC后早芭,進(jìn)行的對象大小大于老年代的可用空間彼城。Eden+From到To復(fù)制的時(shí)候,對象的大小大于To區(qū)域大小,當(dāng)把對象轉(zhuǎn)到老年募壕,這個時(shí)候老年代的空間小于對象大小调炬。
GC信息解讀
[GC (Allocation Failure) [DefNew: 6518K->898K(9216K), 0.0038707 secs] 6518K->4994K(19456K), 0.0042538 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
GC (Allocation Failure) GC的類型,括號里面是GC產(chǎn)生的原因舱馅。
DefNew 垃圾回收期的名稱
6518K->898K(9216K) 6518K代表GC之前大小缰泡,898K代表GC之后的大小。9216K總的大小代嗤。
0.0038707 secs GC暫停的時(shí)間棘钞。
6518K->4994K(19456K) 整個區(qū)域的情況。
[Times: user=0.00 sys=0.00, real=0.00 secs]
user 執(zhí)行GC期間線程消耗的總CPU時(shí)間
sys 操作系統(tǒng)調(diào)用或者等待系統(tǒng)事件等待的時(shí)間
real 應(yīng)用程序停止的時(shí)間干毅。
FullGC(xxxxxxx)
- FullGC(Metadata GC Threashold) 元空間不足觸發(fā)了GC
- FullGC(System.gc()) 手動調(diào)用觸發(fā)GC
- FullGC(Ergonomics)
附錄:JVM內(nèi)存管理參數(shù)
DisableExplicitGC | 默認(rèn)關(guān)閉 | 忽略來自System.gc()方法觸發(fā)的垃圾收集 |
---|---|---|
ExplicitGCInvokesConcurrent | 默認(rèn)關(guān)閉 | 當(dāng)收到System.gc()方法提交的來機(jī)收集申請時(shí),使用CMS收集器進(jìn)行收集 |
UseSerialGC | Client模式的虛擬機(jī)默認(rèn)開啟,其他模式關(guān)閉 | 虛擬機(jī)運(yùn)行在Client模式下的默認(rèn)值,打開此開關(guān)后,使用Serial + Serial Old的收集器組合進(jìn)行內(nèi)存回收 |
UseParNewGC | 默認(rèn)關(guān)閉 | 打開此開關(guān)后,使用ParNew + Serial Old的收集器組合進(jìn)行內(nèi)存回收 |
UseConcMarkSweepGC | 默認(rèn)關(guān)閉 | 打開此開關(guān)后,使用ParNew + CMS + Serial Old的收集器組合進(jìn)行內(nèi)存回收.如果CMS收集器出現(xiàn)Concurrent Mode Failure,則Serial Old收集器將作為后備收集器 |
UseParallelGC | Server模式的虛擬機(jī)默認(rèn)開啟,其他模式關(guān)閉 | 虛擬機(jī)運(yùn)行在Server模式下的默認(rèn)值,打開此開關(guān)后,使用Parallel Scavenge + Serial Old的收集器組合進(jìn)行內(nèi)存回收 |
UseParallelOldGC | 默認(rèn)關(guān)閉 | 打開此開關(guān)后,使用Parallel Scavenge + Parallel Old的收集器組合進(jìn)行內(nèi)存回收 |
SurvivorRatio | 默認(rèn)為8 | 新生代中Eden區(qū)域與Survivor區(qū)域的容量比 |
PretenureSizeThreshold | 無默認(rèn)值 | 直接晉升到老年代的對象大小宜猜,設(shè)置這個參數(shù)后,大于這個參數(shù)的對象將直接在老年代分配 |
MaxTenuringThreshold | 默認(rèn)值為15 | 晉升到老年代的對象年齡,每個對象在堅(jiān)持過一次Minor GC之后,年齡就+1,當(dāng)超過這個參數(shù)值時(shí)就進(jìn)入老年代 |
UseAdaptiveSizePolicy | 默認(rèn)開啟 | 動態(tài)調(diào)整java堆中各個區(qū)域的大小及進(jìn)入老年代的年齡 |
HandlePromotionFailure | jdk1.5及以前是默認(rèn)關(guān)閉,jdk1.6默認(rèn)開啟 | 是否允許分配擔(dān)保失敗,即老年代的剩余空間不足以應(yīng)付新生代的整個Eden和Survivor區(qū)的所有對象都存活的極端情況 |
ParallelGCThreads | 少于或等于8個CPU時(shí)默認(rèn)值為CPU數(shù)量值,多于8個CPU時(shí)比CPU數(shù)量值小 | 設(shè)置并行GC時(shí)進(jìn)行內(nèi)存回收的線程數(shù) |
GCTimeRatio | 默認(rèn)值99 | GC時(shí)間占總時(shí)間的比率.僅在使用Parallel Scavenge收集器時(shí)生效 |
MaxGCPauseMills | 無默認(rèn)值 | 設(shè)置GC最大停頓時(shí)間.僅在使用Parallel Scavenge收集器時(shí)生效 |
CMSInitiatingOccupancyFraction | 默認(rèn)值68 | 設(shè)置CMS收集器在老年代空間被使用多少后觸發(fā)垃圾收集 |
UseCMSCompactAtFullCollection | 默認(rèn)開啟 | 設(shè)置CMS收集器在完成垃圾收集后是否要進(jìn)行一次內(nèi)存碎片整理 |
CMSFullGCsBeforeCompaction | 無默認(rèn)值 | 設(shè)置CMS收集器在進(jìn)行若干次垃圾收集后再啟動一次內(nèi)存碎片整理 |
ScavengeBeforeFullGC | 默認(rèn)開啟 | 在Full GC發(fā)生之前觸發(fā)一次Minor GC |
UseGCOverheadLimit | 默認(rèn)開啟 | 禁止GC過程無限制的執(zhí)行,如果過于頻繁,就直接發(fā)生OutOfMemory |
UseTLAB | Server模式默認(rèn)開啟 | 優(yōu)先在本地線程緩沖區(qū)中分配對象,避免分配內(nèi)存時(shí)的鎖定過程 |
MaxHeapFreeRatio | 默認(rèn)值70 | 當(dāng)Xmx值比Xms值大時(shí),堆可以動態(tài)收縮和擴(kuò)展,這個參數(shù)控制當(dāng)堆空閑大于指定比率時(shí)自動收縮 |
MinHeapFreeRatio | 默認(rèn)值40 | 當(dāng)Xmx值比Xms值大時(shí),堆可以動態(tài)收縮和擴(kuò)展,這個參數(shù)控制當(dāng)堆空閑小于指定比率時(shí)自動收縮 |
MaxPermSize | 大部分情況下默認(rèn)值是64MB | 永久代的最大值 |
即時(shí)編譯參數(shù) | ||
CompileThreshold | Client模式下默認(rèn)值1500,Server模式下默認(rèn)值10000 | 觸發(fā)即時(shí)編譯的閾值 |
OnStackReplacePercentage | Client模式下默認(rèn)值933,Server模式下140 | OSR比率,它是OSR即時(shí)編譯閾值計(jì)算公司的一個參數(shù),用于代替BackEdgeThreshold參數(shù)控制回邊計(jì)數(shù)器的實(shí)際溢出閾值 |
ReservedCodeCacheSize | 大部分情況下默認(rèn)值32MB | 即時(shí)編譯器編譯的代碼緩存使得最大值 |
類型加載參數(shù) | ||
UseSplitVerifier | 默認(rèn)開啟 | 使用依賴StackMapTable信息的類型檢查代替數(shù)據(jù)流分析,以加快字節(jié)碼校驗(yàn)速度 |
FailOverToOldVerifier | 默認(rèn)開啟 | 當(dāng)類型校驗(yàn)失敗時(shí),是否允許回到老的類型推到校驗(yàn)方式進(jìn)行校驗(yàn),如果開啟則允許 |
RelaxAccessControlCheck | 默認(rèn)開啟 | 在校驗(yàn)階段放松對類型訪問性的限制 |
多線程相關(guān)參數(shù) | ||
UseSpinning | Jdk1.6默認(rèn)開啟硝逢,Jdk1.5默認(rèn)關(guān)閉 | 開啟自旋鎖以免線程頻繁的掛起和喚醒 |
PreBolckSpin | 默認(rèn)值10 | 使用自旋鎖時(shí)默認(rèn)的自旋次數(shù) |
UseThreadPriorities | 默認(rèn)開啟 | 使用本地線程優(yōu)先級 |
UseBiasedLocking | 默認(rèn)開啟 | 是否使用偏向鎖,如果開啟則使用 |
UseFastAccessorMethods | 默認(rèn)開啟 | 當(dāng)頻繁反射執(zhí)行某個方法時(shí),生成字節(jié)碼來加快反射的執(zhí)行速度 |
性能參數(shù) | ||
AggressiveOpts | Jdk1.6默認(rèn)開啟姨拥,Jdk1.5默認(rèn)關(guān)閉 | 使用激進(jìn)的優(yōu)化特征,這些特征一般是具備正面和負(fù)面雙重影響的,需要根據(jù)具體應(yīng)用特點(diǎn)分析才能判定是否對性能有好處 |
UseLargePage | 默認(rèn)開啟 | 如果可能,使用大內(nèi)存分頁,這項(xiàng)特性需要操作系統(tǒng)的支持 |
LargePageSizeInBytes | 默認(rèn)值4MB | 使用指定大小的內(nèi)存分頁,這項(xiàng)特性需要操作系統(tǒng)的支持 |
StringCache | 默認(rèn)開啟 | 是否使用字符串緩存,開啟則使用 |
調(diào)試參數(shù) | ||
HeapDumpOnOutOfMemoryError | 默認(rèn)關(guān)閉 | 在發(fā)生內(nèi)存溢出異常時(shí)是否生成堆轉(zhuǎn)儲快照,關(guān)閉則不生成 |
OnOutOfMemoryError | 無默認(rèn)值 | 當(dāng)虛擬機(jī)拋出內(nèi)存溢出異常時(shí),執(zhí)行指令的命令 |
OnError | 無默認(rèn)值 | 當(dāng)虛擬機(jī)拋出ERROR異常時(shí),執(zhí)行指令的命令 |
PrintClassHistogram | 默認(rèn)關(guān)閉 | 使用[ctrl]-[break]快捷鍵輸出類統(tǒng)計(jì)狀態(tài),相當(dāng)于jmap-histo的功能 |
PrintConcurrentLocks | 默認(rèn)關(guān)閉 | 打印J.U.C中的狀態(tài) |
PrintCommandLineFlags | 默認(rèn)關(guān)閉 | 打印啟動虛擬機(jī)時(shí)輸入的非穩(wěn)定參數(shù) |
PrintFlagsFinal | ---- | 顯示所有可設(shè)置的參數(shù)及它們的值(***從JDK 6 update 21開始才可以用) |
PrintFlagsInitial | ---- | 顯示在處理參數(shù)之前所有可設(shè)置的參數(shù)及它們的值,然后直接退出程序 |
PrintCompilation | 默認(rèn)關(guān)閉 | 打印方法即時(shí)編譯信息 |
PrintGC | 默認(rèn)關(guān)閉 | 打印GC信息 |
PrintGCDetails | 默認(rèn)關(guān)閉 | 打印GC的詳細(xì)信息 |
PrintGCTimeStamps | 默認(rèn)關(guān)閉 | 打印GC停頓耗時(shí) |
PrintTenuringDistribution | 默認(rèn)關(guān)閉 | 打印GC后新生代各個年齡對象的大小 |
TraceClassLoading | 默認(rèn)關(guān)閉 | 打印類加載信息 |
TraceClassUnloading | 默認(rèn)關(guān)閉 | 打印類卸載信息 |
PrintInlining | 默認(rèn)關(guān)閉 | 打印方法內(nèi)聯(lián)信息 |
PrintCFGToFile | 默認(rèn)關(guān)閉 | 將CFG圖信息輸出到文件,只有DEBUG版虛擬機(jī)才支持此參數(shù) |
PrintIdealGraphFile | 默認(rèn)關(guān)閉 | 將Ideal圖信息輸出到文件,只有DEBUG版虛擬機(jī)才支持此參數(shù) |
UnlockDiagnosticVMOptions | 默認(rèn)關(guān)閉 | 讓虛擬機(jī)進(jìn)入診斷模式,一些參數(shù)(如PrintAssembly)需要在診斷模式中才能使用 |
PrintAssembly | 默認(rèn)關(guān)閉 | 打印即時(shí)編譯后的二進(jìn)制信息 |