配置举例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
- 1
根据配置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参数配置演示.