Run -> Edit Configuration
-XX:+PrintGCDetails
-Xms30M
-Xmx30M
-Xmn10M
-XX:SurvivorRatio=8
参数含义分别是:
打印GC日志
最小堆内存
最大堆内存
堆中新生代内存
新生代内存中Eden和Survivor大小之比,如果为8表示Eden占80%,另外两个Survivor各占10%
package memory.gc;
/**
* Created by Administrator on 2018-04-11.
*/
public class GCLogTest {
public static void main(String[] args) {
System.out.println(Runtime.getRuntime().maxMemory());
System.out.println(Runtime.getRuntime().totalMemory());
Object obj = new Object();
obj = null;
System.gc();
}
}
程序通过System.gc()使JVM进行了一次Full GC
看到输出的日志如下
30408704
30408704
[Full GC (System.gc()) [TenuredDisconnected from the target VM, address: '127.0.0.1:55874', transport: 'socket'
: 0K->528K(20480K), 0.0029772 secs] 1315K->528K(29696K), [Metaspace: 1840K->1840K(4480K)], 0.0030434 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 82K [0x03800000, 0x04200000, 0x04200000)
eden space 8192K, 1% used [0x03800000, 0x03814928, 0x04000000)
from space 1024K, 0% used [0x04000000, 0x04000000, 0x04100000)
to space 1024K, 0% used [0x04100000, 0x04100000, 0x04200000)
tenured generation total 20480K, used 528K [0x04200000, 0x05600000, 0x05600000)
the space 20480K, 2% used [0x04200000, 0x04284308, 0x04284400, 0x05600000)
Metaspace used 1845K, capacity 2242K, committed 2368K, reserved 4480K
[Full GC : 这是Full GC的标识。
先忽略上面中括号[Full GC ..... ]之间的信息(里面有回收时间sec、回收前->回收后大小),
直接看Heap下面的输出日志:
def new generation total 9216k 说明新生代垃圾回收内存区域总大小为9216k。
这个大小是怎么算出来的呢?
它是:eden space 加上一个 survivor space (也就是from space)的大小,另外一个survivor space (也就是to space)是用来通过复制算法存放存活对象的,不在回收区域之内,所以def new generation total 没有算上它。
对应新生代内存Xmn的大小正好是10M。其中eden space和survivor space(from space 和 to space任意一个)之比8:1。
tenured generation表示老年代内存,20M,加上新生代内存10M,正好30M。
元空间(metaspace)
持久代的空间在JDK8中被彻底地删除后(JDK7没有彻底删除),它被一个叫元空间的区域所替代了。
这样JVM会忽略PermSize和MaxPermSize这两个参数(经过试验,确实如此),还有就是再也看不到java.lang.OutOfMemoryError: PermGen error的异常了。
JDK 8的HotSpot JVM现在使用的是本地内存来表示类的元数据,这个区域就叫做元空间。