java.lang.stackoverflowerror_java.lang.StackOverflowError——如何解决StackOverflowError错误
StackOverflowError在程序棧空間耗盡時(shí)拋出,通常是深度遞歸導(dǎo)致。StackOverflowError繼承了VirtualMachineError類,后者表示JVM已被破壞或資源耗盡。更進(jìn)一步,VirtualMachineError繼承自Error類,應(yīng)用程序不應(yīng)該捕獲這種嚴(yán)重的錯(cuò)誤。不要再throw語句里面拋出這樣的錯(cuò)誤,因?yàn)檫@些錯(cuò)誤是不應(yīng)該發(fā)生的異常條件。StackOverflowError從Java 1.0版本就已存在。
StackOverflowError構(gòu)造函數(shù)
StackOverflowError()和StackOverflowError(String s),后者的String參數(shù)指明了拋出錯(cuò)誤的類名。
The StackOverflowError in Java
當(dāng)一個(gè)函數(shù)被Java程序調(diào)用的時(shí)候,就會在調(diào)用棧上分配棧幀。棧幀包含被調(diào)用函數(shù)的參數(shù)、局部變量和返回地址。返回地址指示了當(dāng)函數(shù)執(zhí)行完畢之后下一步該執(zhí)行哪里。如果創(chuàng)建棧幀時(shí)沒有內(nèi)存空間,JVM就會拋出StackOverflowError。
最常見的耗盡Java棧的案例是遞歸。在遞歸操作中,函數(shù)執(zhí)行時(shí)會調(diào)用自己。使用遞歸要小心,以免拋出StackOverflowError錯(cuò)誤。如下的例子演示了遞歸如何拋出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,遞歸永遠(yuǎn)不會終止。
使用-Xss1M參數(shù)指定線程棧空間大小為1M,這個(gè)例子的執(zhí)行結(jié)果如下:
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
下面的例子演示了類之間有循環(huán)關(guān)系時(shí)的風(fēng)險(xiǎn)。
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());
}
}
當(dāng)創(chuàng)建A對象的時(shí)候需要?jiǎng)?chuàng)建B對象,創(chuàng)建B對象的時(shí)候又要?jiǎng)?chuàng)建A對象,在兩個(gè)類之間形成了循環(huán)依賴,最終導(dǎo)致StackOverflowError。輸出結(jié)果:
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
最簡單的方法就是細(xì)致的檢查stack trace,找出行號的重復(fù)模式。這些重復(fù)的行號代表了被遞歸調(diào)用的代碼。仔細(xì)審查代碼,理解為何遞歸不終止。
如果你確認(rèn)遞歸實(shí)現(xiàn)沒有問題,你可以通過-Xss參數(shù)增加棧的大小,這個(gè)參數(shù)可以在項(xiàng)目配置或命令行指定。
總結(jié)
以上是生活随笔為你收集整理的java.lang.stackoverflowerror_java.lang.StackOverflowError——如何解决StackOverflowError错误的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 升级iOS 16后如何通过LTE进行网络
- 下一篇: kafka metric java,jm