java.lang.stackoverflowerror_java.lang.StackOverflowError——如何解决StackOverflowError错误
StackOverflowError在程序棧空間耗盡時拋出,通常是深度遞歸導致。StackOverflowError繼承了VirtualMachineError類,后者表示JVM已被破壞或資源耗盡。更進一步,VirtualMachineError繼承自Error類,應用程序不應該捕獲這種嚴重的錯誤。不要再throw語句里面拋出這樣的錯誤,因為這些錯誤是不應該發生的異常條件。StackOverflowError從Java 1.0版本就已存在。
StackOverflowError構造函數
StackOverflowError()和StackOverflowError(String s),后者的String參數指明了拋出錯誤的類名。
The StackOverflowError in Java
當一個函數被Java程序調用的時候,就會在調用棧上分配棧幀。棧幀包含被調用函數的參數、局部變量和返回地址。返回地址指示了當函數執行完畢之后下一步該執行哪里。如果創建棧幀時沒有內存空間,JVM就會拋出StackOverflowError。
最常見的耗盡Java棧的案例是遞歸。在遞歸操作中,函數執行時會調用自己。使用遞歸要小心,以免拋出StackOverflowError錯誤。如下的例子演示了遞歸如何拋出StackOverflowError:
public class StackOverflowErrorExample {
public static void recursivePrint(int num) {
System.out.println("Number: " + num);
if(num == 0)
return;
else
recursivePrint(++num);
}
public static void main(String[] args) {
StackOverflowErrorExample.recursivePrint(1);
}
}
如果num為0,遞歸就會終止,但是這里一開始傳入1,每次遞歸都自增1,遞歸永遠不會終止。
使用-Xss1M參數指定線程棧空間大小為1M,這個例子的執行結果如下:
Number: 1
Number: 2
Number: 3
...
Number: 6262
Number: 6263
Number: 6264
Number: 6265
Number: 6266
Exception in thread "main" java.lang.StackOverflowError
at java.io.PrintStream.write(PrintStream.java:480)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
at java.io.PrintStream.write(PrintStream.java:527)
at java.io.PrintStream.print(PrintStream.java:669)
at java.io.PrintStream.println(PrintStream.java:806)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:4)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
at StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:9)
...
More about the StackOverflowError in Java
下面的例子演示了類之間有循環關系時的風險。
class A {
private int aValue;
private B bInstance = null;
public A() {
aValue = 0;
bInstance = new B();
}
@Override
public String toString() {
return "";
}
}
class B {
private int bValue;
private A aInstance = null;
public B() {
bValue = 10;
aInstance = new A();
}
@Override
public String toString() {
return "";
}
}
public class StackOverflowErrorToStringExample {
public static void main(String[] args) {
A obj = new A();
System.out.println(obj.toString());
}
}
當創建A對象的時候需要創建B對象,創建B對象的時候又要創建A對象,在兩個類之間形成了循環依賴,最終導致StackOverflowError。輸出結果:
Exception in thread "main" java.lang.StackOverflowError
at main.java.B.(StackOverflowErrorToStringExample.java:24)
at main.java.A.(StackOverflowErrorToStringExample.java:9)
at main.java.B.(StackOverflowErrorToStringExample.java:24)
at main.java.A.(StackOverflowErrorToStringExample.java:9)
at main.java.B.(StackOverflowErrorToStringExample.java:24)
at main.java.A.(StackOverflowErrorToStringExample.java:9)
...
如何處理StackOverflowError
最簡單的方法就是細致的檢查stack trace,找出行號的重復模式。這些重復的行號代表了被遞歸調用的代碼。仔細審查代碼,理解為何遞歸不終止。
如果你確認遞歸實現沒有問題,你可以通過-Xss參數增加棧的大小,這個參數可以在項目配置或命令行指定。
總結
以上是生活随笔為你收集整理的java.lang.stackoverflowerror_java.lang.StackOverflowError——如何解决StackOverflowError错误的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 升级iOS 16后如何通过LTE进行网络
- 下一篇: linux超链接怎么设置(linux 超