StackOverflowError和OutOfMemoryError之间有什么区别

Ifo*_*est 41 java

StackOverflowError和OutOfMemoryError之间的区别是什么以及如何在应用程序中避免它们?

kos*_*osa 72

简短回答:

  • OutOfMemoryError 与Heap有关.
  • StackOverflowError 与堆栈有关

答案很长:

当您开始时,您JVM可以定义它可以用于处理多少RAM.JVM将其划分为某些存储位置以用于其处理目的,其中两个是Stack&Heap

如果你在内存中有大对象(或)引用的对象,那么你会看到OutofMemoryError.如果您对对象有强引用,则GC无法清除为该对象分配的内存空间.当JVM尝试为新对象分配内存而没有足够的可用空间时,它会抛出,OutofMemoryError因为它无法分配所需的内存量.

如何避免:确保GC不支持不必要的对象

所有局部变量和方法调用相关数据都将在堆栈中.对于每个方法调用,将创建一个堆栈帧,并将本地以及与方法调用相关的数据放置在堆栈帧内.方法执行完成后,将删除堆栈帧.重现这一点的一种方法是,有一个无限循环的方法调用,你会看到stackoverflow错误,因为堆栈帧将填充每个调用的方法数据但不会被释放(删除).

如何避免:确保方法调用结束(不是在无限循环中)


vai*_*olo 10

StackOverflowError当您在另一个内部执行太多方法时(例如无限递归),就会发生这种情况,这受到堆栈大小的限制

OutOfMemoryError当 JVM 耗尽空间来分配在堆上分配的新对象时,就会发生这种情况


Mih*_*eac 6

想象一下,您具有如下功能

public void f(int x) {
    return f(x + 1);
}
Run Code Online (Sandbox Code Playgroud)

呼叫时,呼叫将f一次又一次地呼叫。每次调用时,信息都会存储在堆栈中。由于堆栈的大小受限制,因此您将获得StackOverflowError

现在想象下面的代码:

for (int i = 1; i > 0; i++)
    vector.add(new BigObject());
Run Code Online (Sandbox Code Playgroud)

BigObject普通的Java对象在哪里。如您所见,循环永远不会终止。每个分配都是在堆上完成的,因此将用BigObjects 填充,您将获得一个OutOfMemoryError

回顾一下:

  • OutOfMemoryError 创建对象时抛出
  • StackOverflowError 调用函数时抛出