java gc测试_JVM测试总结_基于Java8(自用)

一、jvm垃圾回收器

jvm的垃圾回收器有serial收集器、parnew收集器、parallel scavenge收集器、serial old 收集器、parallel old收集器、cms收集器、g1收集器

HotSpot虚拟机所包含的收集器:

9d2efb8c60ad0642b183f8661348fd6c.png

图中展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,则说明它们可以搭配使用。虚拟机所处的区域则表示它是属于新生代还是老年代收集器。

新生代收集器:Serial、ParNew、Parallel Scavenge

老年代收集器:CMS、Serial Old、Parallel Old

整堆收集器: G1

二、jvm内存分配担保机制

1、指定Serial+Serial Old作为jvm垃圾回收器

jvm启动参数如下:

-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseSerialGC

其中10M分配给新生代,另外10M分配给老生代。新生代中eden和survivor区的比例为8:1,eden区所分配内存为8M,两个survivor区分别为1M,新生代总可用空间为9M。

测试代码如下:

packagehandlepromotion;public classHandlePromotionFailure {private static final int _1MB = 1024 * 1024;public static voidtestHandlePromotionFailure() {byte[] allocation1 = new byte[2*_1MB];byte[] allocation2 = new byte[2*_1MB];byte[] allocation3 = new byte[2*_1MB];byte[] allocation4 = new byte[4*_1MB];

}public static voidmain(String[] args) {

testHandlePromotionFailure();

}

}

测试结果:

[GC (Allocation Failure) [DefNew: 7127K->526K(9216K), 0.0062127 secs] 7127K->6670K(19456K), 0.0062962 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

Heap

def new generation total 9216K, used 4704K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)

eden space 8192K, 51% used [0x00000000fec00000, 0x00000000ff014930, 0x00000000ff400000)

from space 1024K, 51% used [0x00000000ff500000, 0x00000000ff583918, 0x00000000ff600000)

to space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)

tenured generation total 10240K, used 6144K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)

the space 10240K, 60% used [0x00000000ff600000, 0x00000000ffc00030, 0x00000000ffc00200, 0x0000000100000000)

Metaspace used 2671K, capacity 4486K, committed 4864K, reserved 1056768K

class space used 288K, capacity 386K, committed 512K, reserved 1048576K

测试分析:

eden区依次创建了三个2M的对象,占用内存6M,新生代总可用空间为9M,eden区可用空间为8M,由于9M-6M=3M<4M,从而进行GC,发现survivor区空间不足。此时,JVM就启动了内存分配的担保机制,把这6MB的三个对象直接转移到了老年代。此时就把新生代的空间腾出来了,然后把第四个对象(4MB)放入了eden区中。

2、指定Parallel Scavenge+Serial Old作为jvm垃圾回收器

jvm参数将-XX:+UseSerialGC修改为-XX:+UseParallelGC

测试代码如下:

packagehandlepromotion;public classHandlePromotionFailure {private static final int _1MB = 1024 * 1024;public static voidtestHandlePromotionFailure() {byte[] allocation1 = new byte[2*_1MB];byte[] allocation2 = new byte[2*_1MB];byte[] allocation3 = new byte[2*_1MB];byte[] allocation4 = new byte[4*_1MB];

}public static voidmain(String[] args) {

testHandlePromotionFailure();

}

}

测试结果:

Heap

PSYoungGen total 9216K, used 7292K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)

eden space 8192K, 89% used [0x00000000ff600000,0x00000000ffd1f050,0x00000000ffe00000)

from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)

to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)

ParOldGen total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)

object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000010,0x00000000ff600000)

Metaspace used 2670K, capacity 4486K, committed 4864K, reserved 1056768K

class space used 288K, capacity 386K, committed 512K, reserved 1048576K

接下来我们将第四个对象由4M改为3M,测试结果如下:

[GC (Allocation Failure) [PSYoungGen: 7127K->632K(9216K)] 7127K->6784K(19456K), 0.0053005 secs] [Times: user=0.00 sys=0.00, real=0.01secs]

[Full GC (Ergonomics) [PSYoungGen: 632K->0K(9216K)] [ParOldGen: 6152K->6669K(10240K)] 6784K->6669K(19456K), [Metaspace: 2664K->2664K(1056768K)], 0.0082392 secs] [Times: user=0.05 sys=0.00, real=0.01secs]

Heap

PSYoungGen total 9216K, used 3154K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)

eden space 8192K,38% used [0x00000000ff600000,0x00000000ff914930,0x00000000ffe00000)

from space 1024K,0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)

to space 1024K,0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)

ParOldGen total 10240K, used 6669K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)

object space 10240K,65% used [0x00000000fec00000,0x00000000ff283538,0x00000000ff600000)

Metaspace used 2671K, capacity 4486K, committed 4864K, reserved 1056768Kclass space used 288K, capacity 386K, committed 512K, reserved 1048576K

测试分析:

通过和上面的测试结果对比,我们发现当第四个对象无法放入eden区时,此时不会直接进行GC,而是判断如果要分配的内存>=eden区的一半,那么会直接把要分配的内存放入老年代中。否则进行GC操作,如果survivor区空间不足,则把eden区中的6M的对象直接放入老年代区中,eden区新创建4M的对象。

大概的意思是这种情况下偶尔会发生FullGC,至于原因大概是在使用Parallel Scavenge收集器时,jvm会进行预测,如果晋升到老年代的平均大小大于老年代剩余大小,则认为需要一次FullGC。当虚拟机估算出下次分配可能会发生无法分配的问题时,则会提前发生一次FullGC。

那么针对上面的例子,当gc操作把eden区的6M全部晋升到老年代区中,此时老年代区的大小为10M-6M=4M,jvm预测下一次晋升时老年代空间可能不足,于是提前进行了一次FullGC。

简单验证下,修改jvm参数为-Xms24M -Xmx24M -Xmn10M,将heap内存加大,新生代不变,此时老年代大小为14M。

此时测试结果如下,未发生FullGC:

[GC (Allocation Failure) [PSYoungGen: 7127K->632K(9216K)] 7127K->6784K(23552K), 0.0043651 secs] [Times: user=0.00 sys=0.00, real=0.00secs]

Heap

PSYoungGen total 9216K, used 3786K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)

eden space 8192K,38% used [0x00000000ff600000,0x00000000ff914930,0x00000000ffe00000)

from space 1024K,61% used [0x00000000ffe00000,0x00000000ffe9e030,0x00000000fff00000)

to space 1024K,0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)

ParOldGen total 14336K, used 6152K [0x00000000fe800000, 0x00000000ff600000, 0x00000000ff600000)

object space 14336K,42% used [0x00000000fe800000,0x00000000fee02030,0x00000000ff600000)

Metaspace used 2671K, capacity 4486K, committed 4864K, reserved 1056768Kclass space used 288K, capacity 386K, committed 512K, reserved 1048576K

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值