Java中的StackOverflowError与OutOfMemoryError
时间:2020-01-09 10:34:58 来源:igfitidea点击:
在处理和运行Java应用程序时,我们可能会遇到与内存相关的这两个错误中的任何一个,即StackOverflowError和OutOfMemoryError。在本文中,我们将看到Java中StackOverflowError和OutOfMemoryError之间的区别。
Java中的StackOverflowError
为每个JVM线程创建一个JVM堆栈。每当调用方法时,都会创建一个新框架并将其推送到该线程的JVM堆栈中。每个帧都存储与方法相关的数据,例如局部变量,操作数堆栈和对当前方法类的运行时常量池的引用。一旦方法执行完成,堆栈框(针对该方法)就会弹出堆栈。
如果执行任何方法都需要比允许的堆栈大的堆栈,则Java虚拟机将引发StackOverflowError。当我们具有无终止条件的递归方法时,可能会看到StackOverflowError。
例如,一个Java程序以递归方式打印偶数而没有任何终止条件。
public class StatckOverFlowErrorExample { public static void main(String[] args) { printEven(1); } private static int printEven(int i) { if(i % 2 != 0) { i++; } System.out.println(i); return i + printEven(i + 2); } }
输出:
20808 20810 20812 Exception in thread "main" java.lang.StackOverflowError at java.base/java.io.PrintStream.write(PrintStream.java:605) at java.base/java.io.PrintStream.print(PrintStream.java:676) at java.base/java.io.PrintStream.println(PrintStream.java:812) at com.theitroad.proj.Programs.StatckOverFlowErrorExample.printEven(StatckOverFlowErrorExample.java:14) at com.theitroad.proj.Programs.StatckOverFlowErrorExample.printEven(StatckOverFlowErrorExample.java:15)
Java中的OutOfMemoryError
每当我们为该对象创建新对象时,该对象的内存就会分配到堆上。实例变量和数组也存储在堆中。
一旦存储在堆上的对象没有任何引用,垃圾收集器就会回收该对象的内存。如果存在对对象的引用,则GC无法删除这些对象,如果我们有大量此类引用的对象,并且JVM尝试为新对象分配堆内存,则JVM会抛出java.lang.OutOfMemoryError,因为堆内存不足剩下。
尝试分配大于堆大小的数组也会导致OutOfMemoryError。
public static void main(String[] args) { Integer[] array = new Integer[1000*1000*1000]; }
输出:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Java中的StackOverflowError与OutOfMemoryError
StackOverflowError </ strong> | OutOfMemoryError </ strong> |
当堆栈已满</ em>时,将引发StackOverflowError。 | 当堆空间已满</ em>时,将引发OutOfMemoryError。 |
调用任何方法时,堆栈用于存储与方法相关的数据。因此,如果没有足够的空间来存储方法数据,则会引发StackOverflowError。 | 堆内存用于存储对象,实例变量和数组。因此,当没有空间创建新对象,数组时,将引发OutOfMemoryError。 |
没有终止条件的递归方法会导致StackOverflowError。 | 许多具有实时引用的对象,因此GC无法取消分配这些对象会导致OutOfMemoryError。 |
要避免StackOverflowError,请确保方法正在按逻辑执行并终止,以便可以从堆栈中取出已执行方法的堆栈框架。 | 要避免OutOfMemoryError,请确保不再从任何地方引用不再需要的对象被垃圾收集。还请确保不要创建非常大的对象或者数组。 |