JVM内存分配参数通常是针对堆来说的,因为 java堆是垃圾收集器(GC)管理的主要区域,是Java虚拟机所管理的内存中最大的一块。
整个堆大小=新生代 + 老年代 + 持久代(相对于HotSpot 类型的虚拟机)
目录
1、-Xmx:设置最大堆空间
最大堆空间是指新生代和老年代的大小之和的最大值
我们来测试一下
import java.util.Vector;
public class MaxHeap {
public static void main(String[] args) {
System.out.println("最大内存"+Runtime.getRuntime().maxMemory()/1024/1024+"M");
Vector v=new Vector();
for(int i=0;i<10;i++){
byte[] b=new byte[1024*1024]; //分配1M
v.add(b); //强引用,GC不能释放空间
System.out.println((i+1)+"M 空间被分配");
}
}
}
运行结果
最大内存247M
1M 空间被分配
2M 空间被分配
3M 空间被分配
4M 空间被分配
5M 空间被分配
6M 空间被分配
7M 空间被分配
8M 空间被分配
9M 空间被分配
10M 空间被分配
可见本机默认的最大堆内存空间为247M,10M空间也被正常分配了
接下来我们来通过Xmx参数来修改最大堆空间
在菜单栏选择 Run->Run Configurations
运行结果
2、-Xms:设置最小堆内存
最小堆内存即当JVM启动的时候占有的操作系统内存大小的最小值。
java程序在运行时首先分配最小堆内存的内存大小,然后尽可能地尝试在这个空间内运行程序,如果设置的最小堆内存的大小不能满足应用程序时,JVM会向操作系统提出申请堆空间,直到达到最大堆内存大小位置,如果超出了最大堆内存大小,会抛出OOM异常。
如果说最小堆内存设置得太小了,垃圾收集就会频繁地去操作,用于释放失效的内存空间,会对性能有一定的影响。所以最小堆内存空间大小要由具体应用程序来决定。
我们来测试一下:
import java.util.Vector;
public class MinHeap {
public static void main(String[] args) {
System.out.println("最大内存"+Runtime.getRuntime().maxMemory()/1024/1024+"M");
Vector v=new Vector();
for(int i=0;i<10;i++){
byte[] b=new byte[1024*1024*10]; //分配10M
v.add(b); //强引用,GC不能释放空间
if(v.size()==3){
v.clear(); //清空内存
}
System.out.println("-------");
}
}
}
参数设置:最小堆内存为10M,-XX:+PrintGCDetails表示打印GC的详细信息,默认最大堆内存空间为247M
运行结果
最大内存247M
[GC [DefNew: 624K->320K(3072K), 0.0027563 secs][Tenured: 75K->395K(6848K), 0.0070076 secs] 624K->395K(9920K), [Perm : 149K->149K(12288K)], 0.0098816 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
---
[GC [DefNew: 112K->0K(3136K), 0.0004821 secs][Tenured: 20875K->20876K(27332K), 0.0058795 secs] 20988K->20876K(30468K), [Perm : 149K->149K(12288K)], 0.0065446 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
---
[GC [DefNew: 0K->0K(15680K), 0.0004476 secs][Tenured: 41356K->41356K(55280K), 0.0051294 secs] 41356K->41356K(70960K), [Perm : 149K->149K(12288K)], 0.0057963 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
---
[GC [DefNew: 20480K->0K(31104K), 0.0004693 secs] 61836K->41356K(100032K), 0.0005124 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
---
[GC [DefNew: 20480K->0K(31104K), 0.0185877 secs] 61836K->61836K(100032K), 0.0186214 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
---
[GC [DefNew: 20480K->0K(31104K), 0.0211021 secs][Tenured: 82316K->41355K(89412K), 0.0150908 secs] 82316K->41355K(120516K), [Perm : 149K->149K(12288K)], 0.0380787 secs] [Times: user=0.03 sys=0.00, real=0.04 secs]
---
[GC [DefNew: 20480K->0K(31104K), 0.0004966 secs] 61835K->41355K(100032K), 0.0005308 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
---
[GC [DefNew: 20480K->0K(31104K), 0.0039629 secs] 61835K->61835K(100032K), 0.0039979 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
---
[GC [DefNew: 20480K->0K(31104K), 0.0136943 secs][Tenured: 82315K->41355K(89412K), 0.0131430 secs] 82316K->41355K(120516K), [Perm : 149K->149K(12288K)], 0.0284924 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
---
[GC [DefNew: 20480K->0K(31104K), 0.0005393 secs] 61835K->41355K(100032K), 0.0006814 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
---
Heap
def new generation total 31104K, used 21034K [0x24fe0000, 0x27190000, 0x2a530000)
eden space 27712K, 75% used [0x24fe0000, 0x2646a9d0, 0x26af0000)
from space 3392K, 0% used [0x26e40000, 0x26e40000, 0x27190000)
to space 3392K, 0% used [0x26af0000, 0x26af0000, 0x26e40000)
tenured generation total 68928K, used 41355K [0x2a530000, 0x2e880000, 0x34fe0000)
the space 68928K, 59% used [0x2a530000, 0x2cd92f80, 0x2cd93000, 0x2e880000)
compacting perm gen total 12288K, used 149K [0x34fe0000, 0x35be0000, 0x38fe0000)
the space 12288K, 1% used [0x34fe0000, 0x35005420, 0x35005600, 0x35be0000)
ro space 10240K, 45% used [0x38fe0000, 0x39467290, 0x39467400, 0x399e0000)
rw space 12288K, 54% used [0x399e0000, 0x3a06ace8, 0x3a06ae00, 0x3a5e0000)
当把最小堆内存空间值设大,比如100M:
运行结果
最大内存247M
---
---
[GC [DefNew: 21573K->395K(30720K), 0.0189547 secs] 21573K->20875K(99008K), 0.0192922 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
---
---
[GC [DefNew: 21709K->395K(30720K), 0.0096141 secs] 42189K->31115K(99008K), 0.0096482 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
---
---
[GC [DefNew: 21065K->395K(30720K), 0.0010500 secs] 51785K->31115K(99008K), 0.0010871 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
---
---
[GC [DefNew: 21000K->395K(30720K), 0.0187759 secs] 51720K->51595K(99008K), 0.0188122 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
---
---
Heap
def new generation total 30720K, used 21504K [0x24fe0000, 0x27130000, 0x2a530000)
eden space 27328K, 77% used [0x24fe0000, 0x2647d418, 0x26a90000)
from space 3392K, 11% used [0x26a90000, 0x26af2f60, 0x26de0000)
to space 3392K, 0% used [0x26de0000, 0x26de0000, 0x27130000)
tenured generation total 68288K, used 51200K [0x2a530000, 0x2e7e0000, 0x34fe0000)
the space 68288K, 74% used [0x2a530000, 0x2d730050, 0x2d730200, 0x2e7e0000)
compacting perm gen total 12288K, used 149K [0x34fe0000, 0x35be0000, 0x38fe0000)
the space 12288K, 1% used [0x34fe0000, 0x35005448, 0x35005600, 0x35be0000)
ro space 10240K, 45% used [0x38fe0000, 0x39467290, 0x39467400, 0x399e0000)
rw space 12288K, 54% used [0x399e0000, 0x3a06ace8, 0x3a06ae00, 0x3a5e0000)
可见,GC运行次数明显少了
JVM会试图将系统内存尽可能限制在-Xms中,当内存实际使用量触及到了-Xms大小时,会触发FullGC
如果-Xms值比较大时,系统在运行的初期可以减少垃圾收集的次数和耗时
3、-Xmn:设置新生代大小
新生代的内存大小会影响老年代的内存大小,因为他们俩所占的最大堆空间是一定的。一般新生代的大小设置为整个堆的1/4~1/3
等价于hot spot:-XX:NewSize 新生代初始大小 和 -XX:MaxNewSize
import java.util.Vector;
public class testHeap {
public static void main(String[] args) {
System.out.println("最大内存"+Runtime.getRuntime().maxMemory()/1024/1024+"M");
Vector v=new Vector();
for(int i=0;i<10;i++){
byte[] b=new byte[1024*1024]; //分配10M
v.add(b); //强引用,GC不能释放空间
if(v.size()==3){
v.clear(); //清空内存
}
System.out.println("---");
}
}
}
运行结果
最大内存9M
---
---
[GC [DefNew: 2662K->384K(3712K), 0.0040951 secs] 2662K->2444K(9856K), 0.0041638 secs] [Times: user=0.00 sys=0.02, real=0.01 secs]
---
---
---
[GC [DefNew: 3562K->0K(3712K), 0.0030396 secs] 5622K->4492K(9856K), 0.0030754 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
---
---
---
[GC [DefNew: 3098K->3098K(3712K), 0.0000183 secs][Tenured: 4492K->2444K(6144K), 0.0052126 secs] 7590K->2444K(9856K), [Perm : 149K->149K(12288K)], 0.0052851 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
---
---
Heap
def new generation total 3712K, used 2132K [0x345e0000, 0x349e0000, 0x349e0000)
eden space 3328K, 64% used [0x345e0000, 0x347f5030, 0x34920000)
from space 384K, 0% used [0x34920000, 0x34920000, 0x34980000)
to space 384K, 0% used [0x34980000, 0x34980000, 0x349e0000)
tenured generation total 6144K, used 2444K [0x349e0000, 0x34fe0000, 0x34fe0000)
the space 6144K, 39% used [0x349e0000, 0x34c43010, 0x34c43200, 0x34fe0000)
compacting perm gen total 12288K, used 149K [0x34fe0000, 0x35be0000, 0x38fe0000)
the space 12288K, 1% used [0x34fe0000, 0x35005448, 0x35005600, 0x35be0000)
ro space 10240K, 45% used [0x38fe0000, 0x39467290, 0x39467400, 0x399e0000)
rw space 12288K, 54% used [0x399e0000, 0x3a06ace8, 0x3a06ae00, 0x3a5e0000)
可见一共调用了2次GC以及1次fullgc
我们调大新生代大小为6M时
最大内存9M
---
---
---
---
[GC [DefNew: 4792K->396K(5568K), 0.0035639 secs] 4792K->1420K(9664K), 0.0036134 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
---
---
---
---
[GC [DefNew: 4648K->0K(5568K), 0.0029615 secs] 5672K->3468K(9664K), 0.0030003 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
---
---
Heap
def new generation total 5568K, used 2185K [0x345e0000, 0x34be0000, 0x34be0000)
eden space 4992K, 43% used [0x345e0000, 0x34802428, 0x34ac0000)
from space 576K, 0% used [0x34ac0000, 0x34ac0088, 0x34b50000)
to space 576K, 0% used [0x34b50000, 0x34b50000, 0x34be0000)
tenured generation total 4096K, used 3467K [0x34be0000, 0x34fe0000, 0x34fe0000)
the space 4096K, 84% used [0x34be0000, 0x34f42f98, 0x34f43000, 0x34fe0000)
compacting perm gen total 12288K, used 149K [0x34fe0000, 0x35be0000, 0x38fe0000)
the space 12288K, 1% used [0x34fe0000, 0x35005448, 0x35005600, 0x35be0000)
ro space 10240K, 45% used [0x38fe0000, 0x39467290, 0x39467400, 0x399e0000)
rw space 12288K, 54% used [0x399e0000, 0x3a06ace8, 0x3a06ae00, 0x3a5e0000)
只进行了2次GC
4、设置持久代
持久代不属于堆的一部分,持久代的大小直接决定了系统可以支持多少类定义和多久常量。
-XX:PermSize:设置持久代的初始大小
-XX:MaxPermSize:设置持久代的最大值
5、堆的比例分配
一、-XX:SurvivorRatio 设置新生代中的eden空间与s0(from),s1(to)之间的比例关系
因为s0与s1大小是相等的,它们不过是在每次gc后会交换角色,所以-XX:SurvivorRatio=eden/s0=eden/s1
比如:
可见 eden/from=8192/1024=8
Heap
def new generation total 9216K, used 891K [0x24fe0000, 0x259e0000, 0x259e0000)
eden space 8192K, 10% used [0x24fe0000, 0x250befc0, 0x257e0000)
from space 1024K, 0% used [0x257e0000, 0x257e0000, 0x258e0000)
to space 1024K, 0% used [0x258e0000, 0x258e0000, 0x259e0000)
tenured generation total 6144K, used 0K [0x259e0000, 0x25fe0000, 0x34fe0000)
the space 6144K, 0% used [0x259e0000, 0x259e0000, 0x259e0200, 0x25fe0000)
compacting perm gen total 12288K, used 148K [0x34fe0000, 0x35be0000, 0x38fe0000)
the space 12288K, 1% used [0x34fe0000, 0x35005180, 0x35005200, 0x35be0000)
ro space 10240K, 45% used [0x38fe0000, 0x39467290, 0x39467400, 0x399e0000)
rw space 12288K, 54% used [0x399e0000, 0x3a06ace8, 0x3a06ae00, 0x3a5e0000)
二、-XX:NewRatio:设置老年代与新生代比例
附:完整参数列表
来自于https://blog.csdn.net/wang379275614/article/details/78471604
JVM参数
并行收集器相关
CMS相关
辅助信息