StackOverflowError和OutOfMemoryError之间有什么区别

时间:2012-07-11 15:03:41

标签: java

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

11 个答案:

答案 0 :(得分:67)

简答:

  • OutOfMemoryError与Heap有关。
  • StackOverflowError与堆栈
  • 相关

答案很长:

当您启动JVM时,您可以定义可用于处理的RAM量。 JVM将其划分为某些内存位置以用于其处理目的,其中两个是 Stack& Heap

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

如何避免:确保GC无法使用不必要的对象

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

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

答案 1 :(得分:5)

想象一下,你有类似以下的功能

public void f(int x) {
    return f(x + 1);
}

当您拨打电话时,通话会一次又一次地呼叫f。在每次调用时,一些信息存储在堆栈中。由于堆栈的大小有限,您将获得StackOverflowError

现在想象下面的代码:

for (int i = 1; i > 0; i++)
    vector.add(new BigObject());

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

回顾一下:

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

答案 2 :(得分:3)

当你在另一个内部执行太多方法(例如,使用无限递归)时会发生

StackOverflowError,这受到堆栈的大小的限制。

当JVM空间不足以分配在上分配的新对象时,会发生

OutOfMemoryError

答案 3 :(得分:2)

在Java虚拟机中,定义了几个内存区域:

  1. Java虚拟机堆栈
  2. 堆区
  3. 方法区域
  4. 运行时常量池
  5. 原生方法堆栈
  6. 在上面的所有内容中,您可以选择精确分配给这些内存区域的内存将被修复或将在运行时动态更改。

    现在关于这个问题,OutOfMemoryError适用于上面列出的所有内容。如果将尝试任何内存区域的内存扩展但是没有足够的内存可用于分配,则将抛出OutOfMemoryError

    StackOverFlowError适用于本机方法堆栈 Java虚拟机堆栈。如果线程中的计算需要的堆栈大于允许的堆栈,则抛出StackOverFlowError

    如需详细参考,请阅读THE STRUCTURE OF THE JAVA VIRTUAL MACHINE

答案 4 :(得分:1)

堆和堆栈在内存中有两(2)个区域。

  1. 堆栈内存用于存储本地变量和函数调用。
  2. 堆内存用于存储Java中的对象
  3. 如果堆栈中没有用于存储函数调用或局部变量的内存,JVM将抛出 java.lang.StackOverFlowError

    如果没有更多的堆空间来创建对象,JVM将抛出 java.lang.OutOfMemoryError

答案 5 :(得分:1)

  

以下异常情况与Java虚拟机堆栈相关联:

     

如果线程中的计算需要更大的Java虚拟机   堆栈比允许的堆栈,Java虚拟机抛出一个   的 的StackOverflowError

     

如果可以动态扩展Java虚拟机堆栈,并且   尝试扩展但可以提供不足的内存   实现扩展,或者如果内存不足   可用于为新的创建初始Java虚拟机堆栈   线程,Java虚拟机抛出 OutOfMemoryError

     

以下异常情况与堆相关联:

     

如果计算需要的堆数多于可用的堆   自动存储管理系统,Java虚拟机抛出    OutOfMemoryError

     

以下异常情况与方法区域相关联:

     

如果方法区域中的内存无法满足   分配请求,Java虚拟机抛出一个   的 的OutOfMemoryError

     

以下异常情况与类或接口的运行时常量池的构造相关联:

     

创建类或接口时,如果构造了   运行时常量池需要的内存比可用内存多   在Java虚拟机的方法区域中,Java Virtual   机器抛出 OutOfMemoryError

     

以下异常条件与本机方法堆栈相关联:

     

如果线程中的计算需要比允许的更大的本机方法堆栈,则Java虚拟机会抛出一个   的StackOverflowError。

     

如果本机方法堆栈可以动态扩展和本机方法   尝试堆栈扩展但可以进行不充分的内存   可用,或者如果可以创建的内存不足   新线程的初始本机方法堆栈,Java Virtual   机器抛出 OutOfMemoryError

https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html

2.5.2。 Java虚拟机堆栈

2.5.3。堆

2.5.4。方法区

2.5.5。运行时常量池

2.5.6。本机方法堆栈

2.6。帧

答案 6 :(得分:1)

StackOverflowError

  • 它与堆栈内存有关。
  • 它在堆栈已满时发生。
  • 在调用方法时抛出该异常,并且堆栈中没有剩余空间。
  • 当您在没有适当终止条件的情况下递归调用方法时,就会发生这种情况。
  • 如何避免?确保方法完成执行并离开堆栈内存。

OutOfMemoryError

  • 它与堆内存有关。
  • 它在堆满时发生。
  • 当您创建新对象并且堆中没有剩余空间时,将引发该事件。
  • 在堆内存中创建大量对象时发生。
  • 如何避免?尝试删除对不再需要的对象的引用。

答案 7 :(得分:0)

StackOverflowError:由于应用程序过于冗长而发生堆栈溢出时抛出。

OutOfMemoryError:当Java虚拟机由于内存不足而无法分配对象时抛出,垃圾收集器不再提供更多内存。

答案 8 :(得分:0)

来自Javadocs与JVM堆栈相关的异常条件:

1)如果没有足够的内存可用于为新线程创建初始JVM堆栈,则JVM会抛出OutOfMemoryError。

2)如果线程中的计算需要比允许的更大的JVM堆栈,则JVM会抛出StackOverflowError。

3)如果可以动态扩展JVM堆栈,并且尝试扩展但是没有足够的内存可用于实现扩展,则JVM会抛出OutOfMemoryError。

与Heap相关的特殊情况:

1)如果计算需要的堆量超过自动存储管理系统可用的堆,则JVM会抛出OutOfMemoryError。

答案 9 :(得分:0)

java.lang.StackOverFlowError:
1)当堆栈内存已满时抛出
2)与方法有关的数据,例如参数,局部变量或对对象的引用,都存储在此块中。该方法执行完毕后,将从堆栈中删除此块以及其中存储的数据。
每当您调用方法时,它都必须完成其执行并离开堆栈内存。如果您的方法保留在堆栈中,则堆栈将已满,并且JVM将抛出java.lang.StackOverflowError。 例如:

public class FactorialExample
{
    private static void factorial(int i)
    {
        factorial((i+1) * i);   //calling itself with no terminating condition
    }

    public static void main(String[] args) 
    {
        factorial(1);
    }
}

java.lang.OutOfMemoryError:
1)堆内存已满时抛出。
2)JVM无法将内存分配给新对象。
您在Java中创建的对象存储在堆内存中。当不再需要这些对象时,必须将其从内存中删除。垃圾收集器从堆内存中删除不需要的对象。如果您的对象具有实时引用,则垃圾收集器不会删除它们。它只会删除那些没有实时引用的对象。

答案 10 :(得分:0)

根据JVM规范,有5个数据区域。

对于JVM Stacks数据区域,规范说JVM Stacks的内存大小可以是固定的,也可以像堆区域一样动态可调。

当JVM Stacks内存用完时,有两种情况:
1.如果将JVM堆栈实现为固定大小,则JVM将抛出 StackOverflowError
2.否则,就像堆​​区域一样,当分配更多内存失败时,JVM将抛出 OutOfMemoryError

不仅对于JVM堆栈区域,由于内存资源不足,其他数据区域的内存分配也会发生OutOfMemoryError。

有关更多信息,请参见JVM specification - Run-Time Data Areas