/**
* VM参数有这些:
* -verbose:gc : 表示输出虚拟机中GC的详细情况,输出像: [Full GC 168K->97K(1984K), 0.0253873 secs]
* -Xms20M : 堆内存最小值(单位M)
* -Xmx20M : 堆内存最大值(单位M)
* -Xmn10M : 10M的堆内存分配给新生代
* -XX:+PrintGCDetails : 打印详细GC日志
* -XX:SurvivorRatio=8 : 新生代中Eden区与一个Survivor区的空间比例是8:1
*/
public class Main {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) {
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]; //出现一次Minor(新生代) GC
}
}
运行结果:
[GC (Allocation Failure) [PSYoungGen: 6250K->808K(9216K)] 6250K->4912K(19456K), 0.0020334 secs] [Times: user=0.11 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 9216K, used 7244K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 78% used [0x00000000ff600000,0x00000000ffc49088,0x00000000ffe00000)
from space 1024K, 78% used [0x00000000ffe00000,0x00000000ffeca020,0x00000000fff00000)
to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
ParOldGen total 10240K, used 4104K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 40% used [0x00000000fec00000,0x00000000ff002020,0x00000000ff600000)
Metaspace used 3258K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 357K, capacity 388K, committed 512K, reserved 1048576K
运行参数解析:
GC (Allocation Failure)表示本次GC触发的原因是新生代中没有足够的内存来存放新数据而引发的垃圾回收。
PSYoungGen: 6250K->808K(9216K)表示本次GC使用的是Parallel Scavenge新生代收集器,新生代GC前的内存使用为6250K,GC后为808K,新生代的总容量为9216K(Eden 8192K/Survivor 1024K)。
6250K->4912K(19456K)表示堆GC前已使用内存为6250K,GC后为4912K,堆总内存为19456K。
0.0020334 secs表示GC事件的持续时间(Duration),单位是。
[Times: user=0.11 sys=0.00, real=0.00 secs]表示 GC事件的持续时间,通过多种分类来进行衡量:
- user – 此次垃圾回收, 垃圾收集线程消耗的所有CPU时间(Total CPU time).
- sys – 操作系统调用(OS call) 以及等待系统事件的时间(waiting for system event)
- real – 应用程序暂停的时间(Clock time). 由于串行垃圾收集器(Serial Garbage Collector)只会使用单个线程, 所以 real time 等于 user 以及 system time 的总和。
执行main()中分配allocation4对象的语句时会发生一次Minor(新生代) GC,这次GC的结果是新生代6250KB变为808KB,而总内存占用量则几乎没有减少(因为allocation1、allocation2、allocation3三个对象都是存活的,虚拟机几乎没有找到可回收的对象)。这次GC发生的原因是给allocation4分配内存的时候,发现Eden已经被占用了6MB,剩余空间已不足以分配allocation4所需的4MB内存,因此发生Minor GC。
GC期间虚拟机又发现已有的3个2MB大小的对象全部无法放入Survivor空间(Survivor空间只有1MB大小),所以只好通过分配担保机制提前转移到老年代去。这次GC结束后,4MB的allocation4对象顺利分配在Eden中,因此程序执行完的结果是Eden占用4MB(被allocation4占用),Survivor空闲,老年代被占用6MB(被allocation1、allocation2、allocation3占用)。