Java堆溢出
Java堆用于存储对象的实例,如果对象的数量增加到堆的最大容量就会产生内存溢出现象。
堆的最小值-Xms 堆的最大值-Xmx
idea配置虚拟机参数
static class OOMObject
{
}
public static void main(String[] args)
{
List<OOMObject> list = new ArrayList<>();
while (true)
{
list.add(new OOMObject());
}
}
运行结果
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid16012.hprof ...
Heap dump file created [29135766 bytes in 0.072 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at Scratch.main(scratch.java:44)
虚拟机栈和本地方法栈溢出
参数 -Xss 修改栈容量。
- 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出“StackOverflowError”异常。
- 如果虚拟机栈的内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出OutOfMemoryError异常。
方法区和运行时常量池溢出
运行时常量池是方法区的一部分。
虚拟机参数-XX:PermSize,-XX:MaxPermSize 限制永久代大小。
JDK6及之前的HotSpot虚拟机中常量池分配在永久代,JDK7及以上常量池分配在Java堆之中。所以在JDK6之前通过限制永久代的大小可以使虚拟机抛出OutOfMemoryError异常,JDK7之后要通过限制堆空间才可以。
String::intern():作用是如果字符串常量池中已经包含一个等于此String对象的字符串,则 返回代表 池中的字符串的 String对象的引用;否则,会将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。
public static void main(String[] args)
{
String str1 = new StringBuilder("计算机").append("网络工程").toString();
System.out.println(str1.intern() == str1);
String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2);
}
返回结果:
JDK7及以上
true
false
JDK6
false
false
原因:JDK6中会把首次遇到的字符串放入永久代中保存,返回的是永久代中的引用,而StringBuilder是创建在Java堆中的对象,所以不是一个引用。
JDK7或以上常量池已经移至Java堆中,只需要记录首次出现的引用实例即可,因此intern()返回的引用和由StringBuilder创建的字符串实例使用一个。str2返回false是因为java字符已经不是首次遇到了(在加载sun.misc.Version这个类时加载到常量池中)。
JDK8以后元空间替代了永久代。
参数 -XX:MaxMetaspaceSize 设置元空间的最大值,默认为-1,代表不限制,只受限于本地内存。
-XX:MetaspaceSize: 指定元空间的初始大小,以字节为单位,达到该值就会触发垃圾收集进行类型卸载,同时收集器会对该值进行调整。如果释放了大量的空间,就适当降低该值,如果释放了少量空间,可以适当降低。
-XX:MinMetaspaceFreeRatio: 作用是在垃圾收集之后控制最小的元空间剩余容量的百分比,可减少因为 元空间不足导致的垃圾收集的频率。
本机直接内存溢出
通过-XX:ManDirectMemorySize 来指定直接内存。不指定默认与堆内存一直(-Xmx)