参数-XX:SurvivorRatio用于设置新生代中eden空间和from/to空间的比例。它的含义是:-XX:SurvivorRatio=eden/from=eden/to。如下代码可以观察不同的参数对GC影响
/**
* 默认VM参数:-Xms20m -Xmx20m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
* 修改 -Xmn参数
*/
public static void main(String[] args) {
byte[] a = null;
for(int i=0; i<10; i++) {
a = new byte[1024*1024];
}
}
1.-Xmn1m时,GC日志如下。eden区为1M*(2/(2+2))=0.5M,from=to=0.25M,新生代可使用内存eden + from=768K(如下total 768K)。eden区无法容纳1M的数据,所以触发了一次新生代的GC,GC后还是无法容纳1M数据,导致数据最终都分配在老年代,老年代最终占用10413K。
[GC (Allocation Failure) [DefNew: 507K->256K(768K), 0.0009151 secs] 507K->428K(20224K), 0.0009609 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 768K, used 514K [0x00000000fec00000, 0x00000000fed00000, 0x00000000fed00000)
eden space 512K, 50% used [0x00000000fec00000, 0x00000000fec40b40, 0x00000000fec80000)
from space 256K, 100% used [0x00000000fecc0000, 0x00000000fed00000, 0x00000000fed00000)
to space 256K, 0% used [0x00000000fec80000, 0x00000000fec80000, 0x00000000fecc0000)
tenured generation total 19456K, used 10413K [0x00000000fed00000, 0x0000000100000000, 0x0000000100000000)
the space 19456K, 53% used [0x00000000fed00000, 0x00000000ff72b448, 0x00000000ff72b600, 0x0000000100000000)
Metaspace used 2686K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 286K, capacity 386K, committed 512K, reserved 1048576K
1.-Xmn7m时,GC日志如下。eden=3.5M=3584K,from=to=1792K,新生代可以内存5376K。当初始化第三个数组前的时候时,eden区已经使用2886K,还剩下692K(3584-2886),明显不够分配,触发一次Minor GC。接下来初始化到第六个数组前时,eden区已使用3142K(4695-1553),还剩下442K(3584-3142),也要触发Minor GC。
[GC (Allocation Failure) [DefNew: 2886K->1553K(5376K), 0.0013204 secs] 2886K->1553K(18688K), 0.0013493 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 4695K->1024K(5376K), 0.0010302 secs] 4695K->1552K(18688K), 0.0010404 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 4157K->1024K(5376K), 0.0002867 secs] 4686K->1552K(18688K), 0.0002951 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 5376K, used 3208K [0x00000000fec00000, 0x00000000ff300000, 0x00000000ff300000)
eden space 3584K, 60% used [0x00000000fec00000, 0x00000000fee223a0, 0x00000000fef80000)
from space 1792K, 57% used [0x00000000ff140000, 0x00000000ff240010, 0x00000000ff300000)
to space 1792K, 0% used [0x00000000fef80000, 0x00000000fef80000, 0x00000000ff140000)
tenured generation total 13312K, used 528K [0x00000000ff300000, 0x0000000100000000, 0x0000000100000000)
the space 13312K, 3% used [0x00000000ff300000, 0x00000000ff384148, 0x00000000ff384200, 0x0000000100000000)
Metaspace used 2651K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 285K, capacity 386K, committed 512K, reserved 1048576K
3|0非堆参数配置
除了堆内存,虚拟机还有一些内存用于方法区、栈和直接内存的使用。和堆内存相比,这些内存空间和应用程序的关系不那么密切,但是合理的配置也对系统的性能和稳定有着重要的作用。
3|1方法区配置
方法区主要存放类的元数据信息。在JDK1.6和JDK1.7的版本中,可以使用-XX:PermSize和-XX:MaxPermSize配置永久代大小。在JDK1.8中,永久代被彻底移除,使用心得元数据区存放类的元数据。默认情况元数据区只接受系统的可用内存限制,但是依然可以是参数-XX:MaxMetaspaceSize指定元数据区大小。
3|2栈配置配置
栈是每个线程的私有空间,在虚拟机中可以用-Xss参数来指定线程栈的大小。
public class StackDeepTest {
private static int count = 0;
public static void recursionCall() {
count ++;
recursionCall();
}