JVM学习一

OutOfMemoryError异常

JAVA堆溢出

Java堆用来存储对象实例,只要不断的创建对象,只要在对象数量达到最大堆的容量限制后就会产生内存溢出

通过设置堆的最小值(-Xms)参数和最大值(-Xmx)设置相等来避免堆自动扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
// VM args -Xmx20m -Xms20m
public class HeapOOM {
static class OOMObject{
}
public static void main(String[] args){
List<OOMObject> list = new ArrayList<>();
while(true){
list.add(new OOMObject());
}
}
}

报错信息

1
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

虚拟机栈和本地方法溢出

在HotSpot虚拟机中并不区分虚拟机栈和本地方法栈
栈容量只能通过-Xss来设置
存放基本数据类型(byte,char,boolean,shot,int,long,float,double)和对象的引用类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// VM args -Xss128k
public class JavaVMStackSOF {
private int stackLength = -1;
public void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args){
JavaVMStackSOF oom = new JavaVMStackSOF();
try{
oom.stackLeak();
}catch(Throwable e){
System.out.println("stack length:" + oom.stackLength);
throw e;
}
}
}

方法区和运行时常量溢出

JDK1.6以及之前的版本中,常量池分配在”永久代”中,JDK1.7以后开始“去永久代”
通过-XX:PermSize和-XX:MaxPermSize限制方法区大小
String.intern()是一个Native方法,在JDK1.6之前,intern()方法会将首次遇到的字符串实例复制到”永久代”中,返回的也是”永久代”中的实例,JDK1.7以后不会再复制实例

1
2
3
4
5
6
7
8
9
public class RuntimeConstantPoolOOM {
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);
}
}

所以在JDK1.6和JDK1.7上执行上边的代码会出现不同的结果;JDK1.6中会是两个false,JDK1.7上会是一个true,一个false

本机直接内存溢出

如果您觉得对您有帮助,谢谢您的赞赏!