除了程序计数器,其他区域都规定了OutOfMemoryError,现在逐个去尝试使其出错
思路:堆是用来存放对象的,所以只要一直创建对象即可
结果:失败,未出现堆溢出
解释:执行死循环创建对象,但是这些对象都没有没引用,是可以被GC的对象,当内存不足时,作为非强引用对象,都会被回收
public static void main(String[] args) throws Exception {
while (true){
new Integer(0);
}
}
结果:成功,堆溢出
解释:将创建的对象都纳入数组,完成引用,阻止GC
public static void main(String[] args) throws Exception {
List<Integer> list=new ArrayList<>();
while (true){
list.add(new Integer(0));
}
}
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid12444.hprof ...
Heap dump file created [32471772 bytes in 0.190 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)
...
思路:
a)在Sun HotSpot虚拟机中,Java栈和本地方法栈是合并的,所以一起测试
b)往栈中一直压入栈帧,即方法递归调用,然后打印栈深度
结果:失败,catch语句执行失败
解释:Throwable类有两个子类,一个是Exception异常,一个是Error错误,而堆溢出属于错误Error
public static void main(String[] args) throws Exception {
int stackLength = 0;
try {
method(stackLength);
} catch (Exception e) {
System.out.println(stackLength);
throw e;
}
}
public static void method(int stackLength) {
stackLength++;
method(stackLength);
}
结果:失败,打印出的栈深度为0
解释:基本数据类型是值传递
public static void main(String[] args) throws Exception {
int stackLength = 0;
try {
method(stackLength);
} catch (Throwable e) {
System.out.println(stackLength);
throw e;
}
}
public static void method(int stackLength) {
stackLength++;
method(stackLength);
}
结果:失败,打印出的栈深度为0
解释:包装类Integer在执行完+1动作后,实际上是创建了一个新对象,而不是在原对象上进行修改,而每次递归后创建了新栈帧,在每个新栈帧中都拥有自己的局部变量表,+1后的对象都被这个新栈帧局部变量表的新引用所引用,最初的栈帧main方法的stackLength引用的还是最初的对象,也就是0
public static void main(String[] args) throws Exception {
Integer stackLength = 0;
try {
method(stackLength);
} catch (Throwable e) {
System.out.println(stackLength);
throw e;
}
}
public static void method(Integer stackLength) {
stackLength++;
method(stackLength);
}
结果:成功,栈溢出
解释:方法递归,没有出口,栈帧数量超过栈的最大深度且栈无法再扩展
private static Integer stackLength;
public static void main(String[] args) throws Exception {
stackLength = 0;
try {
method();
} catch (Throwable e) {
System.out.println(stackLength);
throw e;
}
}
public static void method() {
stackLength++;
method();
}
错误日志:
10939
Exception in thread "main" java.lang.StackOverflowError
at com.kingdon.Demo.method(Demo.java:25)
at com.kingdon.Demo.method(Demo.java:26)
...
此处用-Xss128k设置完栈最大内存后,栈最大深度从10939变成了900
思路:
a)方法区存放的是一些运行时的常量,以及类的信息,此处考虑创建大量常量
b)此时想到的就是String类的intern()方法,JDK7以后,intern方法,首先检查运行时常量池是否有该字符串的引用,如果有,直接返回该引用,如果没有,新建一个引用指向该字符串对象,并返回该引用
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=10M; support was removed in 8.0
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=10M; support was removed in 8.0
网上一查,永久代被移除了,引入新概念,元空间,而且运行出来的异常是
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded