Java 堆和栈内存错误
在Java中,运行程序的每个接口、类、对象、变量和方法都存储在计算机内存的不同区域。堆是存储变量、方法和类的值的内存区域,它在运行时动态分配,并根据应用程序的需要进行增长或缩小。另一方面,引用变量、方法和类的名称存储在堆栈内存区域。然而,如果由于某种原因它们的分配没有正确处理,则可能导致本文中将讨论的内存错误。
与栈相关的错误
每当一个进程启动时,它会自动被定义为固定的栈大小。在每个方法调用期间,调用栈上会创建一个调用帧,直到方法调用结束。当在计算机内存的栈空间中没有足够的空间来创建新的栈帧时,我们就会遇到 StackOverflowError。
示例1
下面的示例说明了StackOverflowError。
import java.lang.StackOverflowError;
public class Overflw {
public static void methodA(int n1) {
n1++;
methodB(n1);
}
public static void methodB(int n1) {
n1++;
methodA(n1);
}
public static void main(String []args) {
int n1 = 0;
methodA(n1);
}
}
输出
Exception in thread "main" java.lang.StackOverflowError
at Overflw.methodB(Overflw.java:10)
at Overflw.methodA(Overflw.java:6)
at Overflw.methodB(Overflw.java:10)
at Overflw.methodA(Overflw.java:6)
at Overflw.methodB(Overflw.java:10)
at Overflw.methodA(Overflw.java:6)
at Overflw.methodB(Overflw.java:10)
如您所见,示例1代码的输出会导致StackOverflowError错误。在这里,我们创建了两个带参的自定义方法‘methodA’和‘methodB’。在main方法中,我们声明并初始化了一个名为‘n1’的整数变量,并调用带有参数‘n1’的‘methodA’。现在,‘methodA’调用了带有‘n1’自增值的‘methodB’。再一次,‘methodB’调用了‘methodA’,这个过程循环重复多次。因此,在某一点,为该程序创建的堆栈大小耗尽,导致以下错误。
以下是我们可以采取的措施来处理StackOverflowError错误:
- 给重复调用自己的方法设定适当的终止条件、
- 缩小局部变量或数组的大小可能也有帮助
- 重构代码以避免无限方法调用
示例2
现在,通过这个示例,我们将尝试找到在先前示例中发生的StackOverflowError错误的解决方案。
public class Overflw {
public static void methodA(int n1) {
n1++;
methodB(n1);
}
public static void methodB(int n1) {
n1++;
int n2 = 5;
int mult = n1 * n2;
System.out.println("Value of n1 and n2 multiplication is: " + mult);
}
public static void main(String []args) {
int n1 = 0;
methodA(n1);
}
}
输出
Value of n1 and n2 multiplication is: 10
在示例1中,代码的问题是第6行和第10行没有终止。但是在上面的示例中,我们给出了一条终止程序并打印存储在’mult’中的值的语句。
与堆有关的错误
JVM的两个属性’-Xmx’和’-Xms’确定堆的大小。这个大小会影响值的存储。当JVM在堆内存部分由于空间不足而无法分配值时,我们遇到 OutOfMemoryError
示例1
以下示例说明了OutOfMemoryError。
public class MemoryErr {
public static void main(String[] args) {
String stAray[] = new String[100 * 100 * 100000];
}
}
输出
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at MemoryErr.main(MemoryErr.java:3)
在上述代码中,我们分配了一个大于堆大小的大小,因此我们得到了OutOfMemoryError
我们可以采取以下措施来处理OutOfMemoryError。
- 我们可以使用 -Xmx 和 -Xms JVM 选项来增加堆的大小。
-
使用适合应用程序行为的垃圾收集器也可能有所帮助。
示例2
以下示例演示了如何使用 try 和 catch 块来处理 OutOfMemoryError。
public class MemoryErr {
public static void main(String[] args) {
try {
String stAray[] = new String[100 * 100 * 100000];
} catch(OutOfMemoryError exp) {
System.out.println("Application reached Max size of Heap");
}
}
}
输出
Application reached Max size of Heap
结论
我们从解释每个Java程序所需的两个内存空间开始了本文。在后面的章节中,我们讨论了与堆内存和栈内存相关的错误。