堆参数的调优(我们说JVM调优,其本质就是对参数的调优)
在jdk1.7下(已过时):
其中:
1)-Xms:start(默认为1/64,)
2)-Xmx:max (默认为1/4,即默认堆的最大值是物理内存的1/4)
堆的初始大小和最大值,两者最好一致,避免内存大小调整影响运行的性能
3)-Xmn:new
之前学过堆物理上,新生代和老年代的比例为1:2
所以想要修改这个比例,就是调整 -Xmn 的大小,
但是这个参数,一般不调。
下面两个参数一辈子用不上,因为jdk1.8取消了永久代,变成了元空间。
4)-XX:PermSize:永久代的初始大小
5)-XX:MaxPermSize:永久代的最大值
在jdk1.8下:
1.如何证明jdk1.8的堆内存由新生区+养老区+元空间?
使用-XX:+PrintGCDetails来证明(在IDEA中配置)(它可以输出详细的GC处理日志)
2.如何造成OOM?(堆内存干爆)(当养老代都满了的时候,就会OOM)
(为了快速干爆,记得在IDEA里面修改一下它的-Xms10m -Xmx10m,改为10M)
nextInt(n) 随机生成一个范围在[0 ,n)之间的整型
上面这个例子会OOM的原因是字符串常量池从jdk1.7开始移到了堆里(其实1.8也会,因为毕竟你也在不停地new对象到堆中)
或
结果:(先GC,后Full GC,如果Full GC都不能清理出空间了,则最后报错)
原因:
3.物理内存16G,JVM的堆内存可以分到多少?
初始分配大小(-Xms)为1/64(约200多MB),随着使用,最大(-Xmx)可为1/4(约3.6GB)
通过代码验证:
每一个JavaAPP对应一个runtime对象(见本文JVM图的绿色方框部分)(Runtime Data Area),里面封装了这个app里面的各种信息。
long a = Runtime.getRuntime().totalMemory();
long b = Runtime.getRuntime().maxMemory();
System.out.println(a/(double)1024/1024);
System.out.println(b/(double)1024/1024);
结果:
实际生产,要设-Xms和-Xmx一样大,防止内存忽高忽低,避免在GC后调整堆大小带来的压力。
在IDEA中怎么设置:
配置之后,运行结果:
(可以看到,堆的初始=最大上限,还可以看到详细日志,里面有初生代、老年代、元空间)
而
运行结果里面,通过计算还可以证明物理上,堆内存物理上只分为新生代+养老代:
(图中的篮框里应改为“元空间”,这里写错了)
永久代和元空间最大的区别:
永久代使用的内存是Java虚拟机的堆内存;
元空间使用的内存是本机的物理内存。(所以,默认情况下元空间的大小仅受本地内存的限制)
后面针对-XX:+PrintGCDetails的输出结果,进行了详细讲解,说明了这些输出的具体含义,而不仅仅停留在GC、Full GC了
GC: