JVM-GC總結-配置實戰--第三發
配置舉例1:
vm args:
-Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=3 -XX:MaxPermSize=30m -XX:MaxTenuringThreshold=3 -XX:+PrintHeapAtGC
使用工具:jvisualvm (安裝visual gc 外掛)
根據設定堆記憶體為60m, 因為設定了-XX:NewRatio=2所以年輕代與年老代的比例是1:2,
年輕代 20m,年老代40m, 設定-XX:SurvivorRatio=3 所以 survivor與eden的比例是1:3,
Eden佔年輕代的3/5是12m,s0,s1各佔1/5是4m,從圖中可以看到jvm記憶體分佈符合設定的引數,方法區(非堆)30m.
此時程式剛執行,dump了一下堆,可以看到剛生成的好多物件都是jmx相關的物件
執行程式碼每次增加1m的物件到記憶體,當eden無法建立時會觸發一次minor gc,
這時由於survivor區無法承載eden中的全部物件,所以物件直接進入了老年代,
見圖:
Eden中的物件一部分進入了s0,另一部分直接進入了年老代.
上圖,再次增加物件到eden,觸發了一次minor gc,此時s1無法存放eden中的全部存活物件和s0中的存活物件, 老年代此時承擔了記憶體擔保的角色存放了多餘的物件.
上圖中,由於程式中物件一直是存活的無法回收所以會一直進入老年代無法gc回收掉.
上圖中老年代已滿無法繼續存放物件,此時full gc 有無法回收掉物件所以會報出
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
堆記憶體溢位,程式退出.
看一下最後一次gc時堆中前後的資料對比:
{Heap before GC invocations=9 (full 5):
PSYoungGen total 16384K, used 11264K [0x00000000fec00000, 0x0000000100000000, 0x0000000100000000)
eden space 12288K, 91% used [0x00000000fec00000,0x00000000ff7001d0,0x00000000ff800000)
from space 4096K, 0% used [0x00000000ffc00000,0x00000000ffc00000,0x0000000100000000)
to space 4096K, 0% used [0x00000000ff800000,0x00000000ff800000,0x00000000ffc00000)
PSOldGen total 40960K, used 40572K [0x00000000fc400000, 0x00000000fec00000, 0x00000000fec00000)
object space 40960K, 99% used [0x00000000fc400000,0x00000000feb9f1e0,0x00000000fec00000)
PSPermGen total 21248K, used 8605K [0x00000000fa600000, 0x00000000fbac0000, 0x00000000fc400000)
object space 21248K, 40% used [0x00000000fa600000,0x00000000fae677a0,0x00000000fbac0000)
Heap after GC invocations=9 (full 5):
PSYoungGen total 16384K, used 11264K [0x00000000fec00000, 0x0000000100000000, 0x0000000100000000)
eden space 12288K, 91% used [0x00000000fec00000,0x00000000ff7001d0,0x00000000ff800000)
from space 4096K, 0% used [0x00000000ffc00000,0x00000000ffc00000,0x0000000100000000)
to space 4096K, 0% used [0x00000000ff800000,0x00000000ff800000,0x00000000ffc00000)
PSOldGen total 40960K, used 40538K [0x00000000fc400000, 0x00000000fec00000, 0x00000000fec00000)
object space 40960K, 98% used [0x00000000fc400000,0x00000000feb969f8,0x00000000fec00000)
PSPermGen total 21248K, used 8537K [0x00000000fa600000, 0x00000000fbac0000, 0x00000000fc400000)
object space 21248K, 40% used [0x00000000fa600000,0x00000000fae56550,0x00000000fbac0000)
}
此次測試程式碼:
public class JConsoleTest {
/**
* 記憶體佔位符物件 大約64k
*/
static class ConObj{
public byte[] placeholder = new byte[1024 * 1024];
}
public static void fillHeap(int num) throws InterruptedException {
List<ConObj> list = new ArrayList<ConObj>();
for(int i = 0;i < num;i++){
Thread.sleep(500);
list.add(new ConObj());
}
//由於方法未執行完畢 list尚在作用域中 此時 執行gc 會導致回收不掉
//System.gc();
}
/**
* 設定例項:
* 1)vm args:
* -Xms1024m -Xmx1024m -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m
*
* 2)vm args:
* -Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=3 -XX:MaxPermSize=30m -XX:MaxTenuringThreshold=3 -XX:+PrintHeapAtGC
*
* 演示jconsole的記憶體頁籤 觀察 eden survivor
* vm args: -Xms100m -Xmx100m -XX:+UseSerialGC
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
Thread.sleep(30000);
fillHeap(100);
//可以回收掉
System.gc();
fillHeap(100);
fillHeap(100);
System.gc();
synchronized (JConsoleTest.class){
JConsoleTest.class.wait();
}
}
}
配置舉例2
-Xmx60m -Xms60m -Xmn30m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:MaxTenuringThreshold=3 -XX:+PrintGCApplicationStoppedTime -XX:+PrintHeapAtGC
根據配置jvm堆大小為60m,其中分配給年輕代30m,年輕代中eden和s0,s1的比例預設是8:1, eden 24m,s0,s1各3m,
上圖第一次觸發minor gc,同1老年代記憶體擔保承擔,很多物件沒有經過survivor直接進入了老年代
第一次minor gc的堆前後對比:
{Heap before GC invocations=0 (full 0):
par new generation total 27648K, used 24576K [0x00000000f7200000, 0x00000000f9000000, 0x00000000f9000000)
eden space 24576K, 100% used [0x00000000f7200000, 0x00000000f8a00000, 0x00000000f8a00000)
from space 3072K, 0% used [0x00000000f8a00000, 0x00000000f8a00000, 0x00000000f8d00000)
to space 3072K, 0% used [0x00000000f8d00000, 0x00000000f8d00000, 0x00000000f9000000)
concurrent mark-sweep generation total 30720K, used 0K [0x00000000f9000000, 0x00000000fae00000, 0x00000000fae00000)
concurrent-mark-sweep perm gen total 21248K, used 8687K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
Heap after GC invocations=1 (full 0):
par new generation total 27648K, used 3007K [0x00000000f7200000, 0x00000000f9000000, 0x00000000f9000000)
eden space 24576K, 0% used [0x00000000f7200000, 0x00000000f7200000, 0x00000000f8a00000)
from space 3072K, 97% used [0x00000000f8d00000, 0x00000000f8fefd98, 0x00000000f9000000)
to space 3072K, 0% used [0x00000000f8a00000, 0x00000000f8a00000, 0x00000000f8d00000)
concurrent mark-sweep generation total 30720K, used 8194K [0x00000000f9000000, 0x00000000fae00000, 0x00000000fae00000)
concurrent-mark-sweep perm gen total 21248K, used 8687K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
}
第一次minor gc 應用暫停時間:
Total time for which application threads were stopped: 0.0215440 seconds – 21.5ms
上圖是通過System.gc()觸發了一次full gc之後的jvm記憶體分佈.
下面是full gc 前後heap前後對比:
{Heap before GC invocations=1 (full 0):
par new generation total 27648K, used 17646K [0x00000000f7200000, 0x00000000f9000000, 0x00000000f9000000)
eden space 24576K, 59% used [0x00000000f7200000, 0x00000000f804bb48, 0x00000000f8a00000)
from space 3072K, 97% used [0x00000000f8d00000, 0x00000000f8fefd98, 0x00000000f9000000)
to space 3072K, 0% used [0x00000000f8a00000, 0x00000000f8a00000, 0x00000000f8d00000)
concurrent mark-sweep generation total 30720K, used 8194K [0x00000000f9000000, 0x00000000fae00000, 0x00000000fae00000)
concurrent-mark-sweep perm gen total 21248K, used 8703K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
Heap after GC invocations=2 (full 1):
par new generation total 27648K, used 0K [0x00000000f7200000, 0x00000000f9000000, 0x00000000f9000000)
eden space 24576K, 0% used [0x00000000f7200000, 0x00000000f7200000, 0x00000000f8a00000)
from space 3072K, 0% used [0x00000000f8d00000, 0x00000000f8d00000, 0x00000000f9000000)
to space 3072K, 0% used [0x00000000f8a00000, 0x00000000f8a00000, 0x00000000f8d00000)
concurrent mark-sweep generation total 30720K, used 923K [0x00000000f9000000, 0x00000000fae00000, 0x00000000fae00000)
concurrent-mark-sweep perm gen total 21248K, used 8698K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
}
應用暫停時間:
Total time for which application threads were stopped: 0.0292275 seconds – 29ms
繼續新增物件觸發minor gc
![這裡寫圖片描述](https://img-blog.csdn.net/201504231118209{Heap before GC invocations=2 (full 1):
par new generation total 27648K, used 24576K [0x00000000f7200000, 0x00000000f9000000, 0x00000000f9000000)
eden space 24576K, 100% used [0x00000000f7200000, 0x00000000f8a00000, 0x00000000f8a00000)
from space 3072K, 0% used [0x00000000f8d00000, 0x00000000f8d00000, 0x00000000f9000000)
to space 3072K, 0% used [0x00000000f8a00000, 0x00000000f8a00000, 0x00000000f8d00000)
concurrent mark-sweep generation total 30720K, used 923K [0x00000000f9000000, 0x00000000fae00000, 0x00000000fae00000)
concurrent-mark-sweep perm gen total 21248K, used 8711K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
Heap after GC invocations=3 (full 1):
par new generation total 27648K, used 395K [0x00000000f7200000, 0x00000000f9000000, 0x00000000f9000000)
eden space 24576K, 0% used [0x00000000f7200000, 0x00000000f7200000, 0x00000000f8a00000)
from space 3072K, 12% used [0x00000000f8a00000, 0x00000000f8a62f30, 0x00000000f8d00000)
to space 3072K, 0% used [0x00000000f8d00000, 0x00000000f8d00000, 0x00000000f9000000)
concurrent mark-sweep generation total 30720K, used 923K [0x00000000f9000000, 0x00000000fae00000, 0x00000000fae00000)
concurrent-mark-sweep perm gen total 21248K, used 8711K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
}or gc 回收了eden中的大部分物件.
程式暫停時間:
Total time for which application threads were stopped: 0.0039866 seconds
配置2程式碼:
public class JConsoleTest {
/**
* 記憶體佔位符物件 大約64k
*/
static class ConObj{
public byte[] placeholder = new byte[1024 * 1024];
}
public static void fillHeap(int num) throws InterruptedException {
List<ConObj> list = new ArrayList<ConObj>();
for(int i = 0;i < num;i++){
Thread.sleep(500);
list.add(new ConObj());
}
//由於方法未執行完畢 list尚在作用域中 此時 執行gc 會導致回收不掉
//System.gc();
}
/**
* 設定例項:
* 1)vm args:
* -Xms1024m -Xmx1024m -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m
*
* 2)vm args:
* -Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=3 -XX:MaxPermSize=30m -XX:MaxTenuringThreshold=3 -XX:+PrintHeapAtGC
*
* 3) vm args:
* -Xmx60m -Xms60m -Xmn30m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:MaxTenuringThreshold=3 -XX:+PrintGCApplicationStoppedTime -XX:+PrintHeapAtGC
* 演示jconsole的記憶體頁籤 觀察 eden survivor
* vm args: -Xms100m -Xmx100m -XX:+UseSerialGC
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
Thread.sleep(15000);
fillHeap(20);
//可以回收掉
System.gc();
fillHeap(20);
fillHeap(5);
fillHeap(20);
System.gc();
synchronized (JConsoleTest.class){
JConsoleTest.class.wait();
}
}
}
上述是倆個較為簡單的jvm引數配置演示.