- 打開(kāi)GC 跟蹤
- -verbose:gc
- -XX:+printGC
可以打印GC的簡(jiǎn)要信息
[GC 4790K->374K(15872K), 0.0001606 secs]
[GC 4790K->374K(15872K), 0.0001474 secs]
[GC 4790K->374K(15872K), 0.0001563 secs]
[GC 4790K->374K(15872K), 0.0001682 secs]
跟蹤參數(shù) 打印更詳細(xì)的
-XX:+PrintGCDetails
打印GC詳細(xì)信息-XX:+PrintGCTimeStamps
打印CG發(fā)生的時(shí)間戳-
例
[GC[DefNew: 4416K->0K(4928K), 0.0001897 secs]
4790K->374K(15872K), 0.0002232 secs]
[Times: user=0.00 sys=0.00, real=0.00 secs]
下面是我在JDK 1.8 執(zhí)行程序 完整的GC日志
可以看到新生代、老年代 和 元空間的大小
- 打印日志中 -Xloggc:log/gc.log
- 指定GC log的位置劝萤,以文件輸出
-XX:+PrintHeapAtGC(每次一次GC后查近,都打印堆信息)
-
-XX:+TraceClassLoading
-
監(jiān)控類(lèi)的加載
類(lèi)似這樣Object 最先加載 然后刷刷刷的 一堆
-
-
-XX:+PrintClassHistogram(按下Ctrl+Break后劣纲,打印類(lèi)的信息:
)
其中一段
-Xmx –Xms(這個(gè)是很重要的參數(shù))
- Xmx20m -Xms5m 運(yùn)行代碼:
System.out.print("Xmx=");
System.out.println(Runtime.getRuntime().maxMemory()/1024.0/1024+"M");
System.out.print("free mem=");
System.out.println(Runtime.getRuntime().freeMemory()/1024.0/1024+"M");
System.out.print("total mem=");
System.out.println(Runtime.getRuntime().totalMemory()/1024.0/1024+"M");
out:
Xmx=18.0M
free mem=3.671600341796875M
total mem=5.5M
- -Xmn(絕對(duì)值)
設(shè)置新生代大小 - -XX:NewRatio(比例)
- 新生代(eden+2*s)和老年代(不包含永久區(qū))的比值
4 表示 新生代:老年代=1:4,即年輕代占堆的1/5
- 新生代(eden+2*s)和老年代(不包含永久區(qū))的比值
- -XX:SurvivorRatio
- 設(shè)置兩個(gè)Survivor區(qū)和eden的比
- 8表示 兩個(gè)Survivor :eden=2:8车吹,即一個(gè)Survivor占年輕代的1/10
//-Xmx20m -Xms20m -Xmn1m -XX:+PrintGCDetails
public static void main(String[] args) {
byte[] b=null;
for(int i=0;i<10;i++)
b=new byte[1*1024*1024];
}
--
- 沒(méi)有觸發(fā)GC
- 全部分配在老年代
堆的分配參數(shù)
- -XX:+HeapDumpOnOutOfMemoryError
OOM時(shí)導(dǎo)出堆到文件 轉(zhuǎn)存堆信息(非常有用)
- -XX:+HeapDumpPath
導(dǎo)出OOM的路徑
例子:
Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=d:/a.dump
Vector v=new Vector();
for(int i=0;i<25;i++)
v.add(new byte[1*1024*1024]);
- -XX:OnOutOfMemoryError
在OOM時(shí),執(zhí)行一個(gè)腳本
"-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p“
當(dāng)程序OOM時(shí),在D:/a.txt中將會(huì)生成線程的dump
可以在OOM時(shí)歧强,發(fā)送郵件,甚至是重啟程序
%p是當(dāng)前進(jìn)程的Pid
堆的分配參數(shù) – 總結(jié)
- 根據(jù)實(shí)際事情調(diào)整新生代和幸存代的大小
- 官方推薦新生代占堆的3/8
- 幸存代占新生代的1/10
- 在OOM時(shí)为肮,記得Dump出堆摊册,確保可以排查現(xiàn)場(chǎng)問(wèn)題
元空間 (HotSpot 1.8 去掉永久代 而新增的)
- -XX:MaxMetaspaceSize (默認(rèn)情況下颊艳,-XX:MaxMetaspaceSize的值沒(méi)有限制茅特,因此元空間甚至可以延伸到交換區(qū),但是這時(shí)候當(dāng)我們進(jìn)行本地內(nèi)存分配時(shí)將會(huì)失敗棋枕。)
- -XX:MetaspaceSize白修,初始空間大小
除了上面兩個(gè)指定大小的選項(xiàng)以外,還有兩個(gè)與 GC 相關(guān)的屬性:
- -XX:MinMetaspaceFreeRatio重斑,在GC之后兵睛,最小的Metaspace剩余空間容量的百分比,減少為分配空間所導(dǎo)致的垃圾收集
- -XX:MaxMetaspaceFreeRatio,在GC之后祖很,最大的Metaspace剩余空間容量的百分比累盗,減少為釋放空間所導(dǎo)致的垃圾收集
棧大小分配
- -Xss
-通常只有幾百K- 決定了函數(shù)調(diào)用的深度
- 每個(gè)線程都有獨(dú)立的棧空間
- 局部變量突琳、參數(shù) 分配在棧上
例子:
/*
遞歸調(diào)用
-Xss128K
deep of calling = 701
java.lang.StackOverflowError
-Xss256K
deep of calling = 1817
java.lang.StackOverflowError
*/
public class TestStackDeep {
private static int count=0;
public static void recursion(long a,long b,long c){
long e=1,f=2,g=3,h=4,i=5,k=6,q=7,x=8,y=9,z=10;
count++;
recursion(a,b,c);
}
public static void main(String args[]){
try{
recursion(0L,0L,0L);
}catch(Throwable e){
System.out.println("deep of calling = "+count);
e.printStackTrace();
}
}
}