什么导致 java.lang.StackOverflowError
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3197708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What causes a java.lang.StackOverflowError
提问by Ivan
What can cause a java.lang.StackOverflowError
? The stack printout that I get is not very deep at all (only 5 methods).
什么会导致java.lang.StackOverflowError
? 我得到的堆栈打印输出根本不是很深(只有 5 种方法)。
回答by nsayer
One of the (optional) arguments to the JVM is the stack size. It's -Xss. I don't know what the default value is, but if the total amount of stuff on the stack exceeds that value, you'll get that error.
JVM 的(可选)参数之一是堆栈大小。这是-Xss。我不知道默认值是什么,但是如果堆栈上的总数量超过该值,您将收到该错误。
Generally, infinite recursion is the cause of this, but if you were seeing that, your stack trace would have more than 5 frames.
通常,无限递归是造成这种情况的原因,但如果您看到了这一点,您的堆栈跟踪将超过 5 帧。
Try adding a -Xss argument (or increasing the value of one) to see if this goes away.
尝试添加 -Xss 参数(或增加 1 的值)以查看是否会消失。
回答by ptoinson
What actually causes a java.lang.StackOverflowError is typically unintentional recursion. For me it's often when I intended to call a super method for the overidden method. Such as in this case:
真正导致 java.lang.StackOverflowError 的原因通常是无意的递归。对我来说,经常是当我打算为被覆盖的方法调用一个超级方法时。例如在这种情况下:
public class Vehicle {
public void accelerate(float acceleration, float maxVelocity) {
// set the acceleration
}
}
public class SpaceShip extends Vehicle {
@Override
public void accelerate(float acceleration, float maxVelocity) {
// update the flux capacitor and call super.accelerate
// oops meant to call super.accelerate(acceleration, maxVelocity);
// but accidentally wrote this instead. A StackOverflow is in our future.
this.accelerate(acceleration, maxVelocity);
}
}
First, it's useful to know what happens behind the scenes when we call a function. The arguments and the address of where the method was called is pushed on the stack (see http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management) so that the called method can access the arguments and so that when the called method is completed, execution can continue after the call. But since we are calling this.accelerate(acceleration, maxVelocity) recursively (recursion is loosely when a method calls itself. For more info see http://en.wikipedia.org/wiki/Recursion_(computer_science)) we are in a situation known as infinite recursion and we keep piling the arguments and return address on the call stack. Since the call stack is finite in size, we eventually run out of space. The running out of space on the call stack is known as overflow. This is because we are trying to use more stack space than we have and the data literally overflows the stack. In the Java programming language, this results in the runtime exception java.lang.StackOverflow and will immediately halt the program.
首先,当我们调用一个函数时,了解幕后发生了什么是很有用的。参数和调用方法的地址被压入堆栈(参见http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management),以便被调用的方法可以访问参数,这样当被调用的方法完成,调用后可以继续执行。但由于我们以递归方式调用 this.accelerate(acceleration, maxVelocity)(当方法调用自身时,递归是松散的。有关更多信息,请参见http://en.wikipedia.org/wiki/Recursion_(computer_science)) 我们处于一种称为无限递归的情况,我们不断在调用堆栈上堆积参数和返回地址。由于调用堆栈的大小是有限的,我们最终会耗尽空间。调用堆栈上的空间不足称为溢出。这是因为我们试图使用比我们拥有的更多的堆栈空间,并且数据确实溢出了堆栈。在 Java 编程语言中,这会导致运行时异常 java.lang.StackOverflow 并将立即停止程序。
The above example is somewhat simplified (although it happens to me more than I'd like to admit.) The same thing can happen in a more round about way making it a bit harder to track down. However, in general, the StackOverflow is usually pretty easy to resolve, once it occurs.
上面的例子稍微简化了(尽管它发生在我身上的次数比我想承认的要多。)同样的事情可能会以更全面的方式发生,这使得追踪变得有点困难。但是,一般来说,StackOverflow 一旦发生通常很容易解决。
In theory, it is also possible to have a stack overflow without recursion, but in practice, it would appear to be a fairly rare event.
理论上,也有可能在没有递归的情况下发生堆栈溢出,但在实践中,这似乎是一个相当罕见的事件。
回答by Thota Srinath
Check for any recusive calls for methods. Mainly it is caused when there is recursive call for a method. A simple example is
检查任何对方法的递归调用。主要是在递归调用方法时引起的。一个简单的例子是
public static void main(String... args) {
Main main = new Main();
main.testMethod(1);
}
public void testMethod(int i) {
testMethod(i);
System.out.println(i);
}
Here the System.out.println(i); will be repeatedly pushed to stack when the testMethod is called.
这里是 System.out.println(i); 调用 testMethod 时将被反复推入堆栈。
回答by Singh
I created a program with hibernate, in which I created two POJO classes, both with an object of each other as data members. When in the main method I tried to save them in the database I also got this error.
我用 hibernate 创建了一个程序,在其中我创建了两个 POJO 类,它们都以彼此的对象作为数据成员。当在主方法中我试图将它们保存在数据库中时,我也遇到了这个错误。
This happens because both of the classes are referring each other, hence creating a loop which causes this error.
发生这种情况是因为两个类都在相互引用,因此创建了一个导致此错误的循环。
So, check whether any such kind of relationships exist in your program.
因此,请检查您的程序中是否存在任何此类关系。
回答by IntelliJ Amiya
When a function call is invoked by a Java application, a stack frame is allocated on the call stack. The stack frame contains the parameters of the invoked method, its local parameters, and the return address of the method.
当 Java 应用程序调用函数调用时,会在调用堆栈上分配一个堆栈帧。堆栈帧包含被调用方法的参数、其本地参数和方法的返回地址。
The return address denotes the execution point from which, the program execution shall continue after the invoked method returns. If there is no space for a new stack frame then, the StackOverflowErroris thrown by the Java Virtual Machine (JVM).
返回地址表示被调用方法返回后程序继续执行的执行点。如果没有空间用于新的堆栈帧,则Java 虚拟机 (JVM)会抛出StackOverflowError。
The most common case that can possibly exhaust a Java application's stack is recursion.
可能耗尽 Java 应用程序堆栈的最常见情况是递归。
Please Have a look
请看一看
How to solve StackOverflowError
如何解决 StackOverflowError
回答by Julz Etnalob
In my case I have two activities. In the second activity I forgot to put super on the onCreate method.
就我而言,我有两项活动。在第二个活动中,我忘记将 super 放在 onCreate 方法上。
super.onCreate(savedInstanceState);
回答by Marzieh Ghadirinia
Stack Overflow exceptions can occur when a thread stack continues to grow in size until reaching the maximum limit.
当线程堆栈的大小继续增长直到达到最大限制时,可能会发生堆栈溢出异常。
Adjusting the Stack Sizes (Xss and Xmso) options...
调整堆栈大小(Xss 和 Xmso)选项...
I suggest you see this link: http://www-01.ibm.com/support/docview.wss?uid=swg21162896There are many possible causes to a StackOverflowError, as you can see in the link....
我建议您查看此链接:http: //www-01.ibm.com/support/docview.wss?uid=swg21162896 StackOverflowError 的可能原因有很多,您可以在链接中看到...
回答by DebanjanB
What is java.lang.StackOverflowError
什么是 java.lang.StackOverflowError
The error java.lang.StackOverflowError
is thrown to indicate that the application's stack was exhausted, due to deep recursion i.e your program/script recurses too deeply.
java.lang.StackOverflowError
抛出错误表明应用程序的堆栈已耗尽,这是由于深度递归,即您的程序/脚本递归得太深。
Details
细节
The StackOverflowError
extends VirtualMachineError
class which indicates that the JVM have been or have run out of resources and cannot operate further. The VirtualMachineError
which extends the Error
class is used to indicate those serious problems that an application should not catch. A method may not declare such errors in its throw
clause because these errors are abnormal conditions that was never expected to occur.
该StackOverflowError
扩展VirtualMachineError
类这表明JVM已经或有资源的耗尽而无法进一步操作。将VirtualMachineError
它扩展了Error
类用于指示那些严重的问题,应用程序不应该捕获。方法可能不会在其throw
子句中声明此类错误,因为这些错误是从未预料到会发生的异常情况。
An Example
一个例子
Minimal, Complete, and Verifiable Example
:
Minimal, Complete, and Verifiable Example
:
package demo;
public class StackOverflowErrorExample {
public static void main(String[] args)
{
StackOverflowErrorExample.recursivePrint(1);
}
public static void recursivePrint(int num) {
System.out.println("Number: " + num);
if(num == 0)
return;
else
recursivePrint(++num);
}
}
Console Output
控制台输出
Number: 1
Number: 2
.
.
.
Number: 8645
Number: 8646
Number: 8647Exception in thread "main" java.lang.StackOverflowError
at java.io.FileOutputStream.write(Unknown Source)
at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
at java.io.BufferedOutputStream.flush(Unknown Source)
at java.io.PrintStream.write(Unknown Source)
at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
at java.io.OutputStreamWriter.flushBuffer(Unknown Source)
at java.io.PrintStream.newLine(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:11)
at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
.
.
.
at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
Explaination
说明
When a function call is invoked by a Java Application, a stack frameis allocated on the call stack. The stack frame
contains the parameters of the invoked method, its local parameters, and the return address of the method. The return address denotes the execution point from which, the program execution shall continue after the invoked method returns. If there is no space for a new stack frame then, the StackOverflowError
is thrown by the Java Virtual Machine (JVM).
当一个函数调用是由Java应用程序调用时,堆栈帧的分配上调用堆栈。该stack frame
包含调用的方法,它的本地参数和方法的返回地址的参数。返回地址表示被调用方法返回后程序继续执行的执行点。如果没有空间用于新的堆栈帧,StackOverflowError
则由 Java 虚拟机 (JVM) 抛出。
The most common case that can possibly exhaust a Java application's stack is recursion. In recursion, a method invokes itself during its execution. Recursion
one of the most powerful general-purpose programming technique, but must be used with caution, in order for the StackOverflowError
to be avoided.
可能耗尽 Java 应用程序堆栈的最常见情况是递归。在递归中,方法在执行期间调用自身。Recursion
最强大的通用编程技术之一,但必须谨慎使用,StackOverflowError
以避免 。
References
参考
回答by Emerica
Solution for Hibernate users when parsing datas:
Hibernate用户解析数据时的解决方案:
I had this error because I was parsing a list of objects mapped on both sides @OneToMany
and @ManyToOne
to json using Hymanson which caused an infinite loop.
我遇到了这个错误,因为我正在解析一个对象列表,这些对象映射在两边@OneToMany
并@ManyToOne
使用 Hymanson解析到 json,这导致了一个无限循环。
If you are in the same situation you can solve this by using @JsonManagedReference
and @JsonBackReference
annotations.
如果您处于相同的情况,则可以通过使用@JsonManagedReference
和@JsonBackReference
注释来解决此问题。
Definitions from API :
来自 API 的定义:
JsonManagedReference (https://fasterxml.github.io/Hymanson-annotations/javadoc/2.5/com/fasterxml/Hymanson/annotation/JsonManagedReference.html) :
Annotation used to indicate that annotated property is part of two-way linkage between fields; and that its role is "parent" (or "forward") link. Value type (class) of property must have a single compatible property annotated with JsonBackReference. Linkage is handled such that the property annotated with this annotation is handled normally (serialized normally, no special handling for deserialization); it is the matching back reference that requires special handling
JsonBackReference: (https://fasterxml.github.io/Hymanson-annotations/javadoc/2.5/com/fasterxml/Hymanson/annotation/JsonBackReference.html):
Annotation used to indicate that associated property is part of two-way linkage between fields; and that its role is "child" (or "back") link. Value type of the property must be a bean: it can not be a Collection, Map, Array or enumeration. Linkage is handled such that the property annotated with this annotation is not serialized; and during deserialization, its value is set to instance that has the "managed" (forward) link.
JsonManagedReference(https://fasterxml.github.io/Hymanson-annotations/javadoc/2.5/com/fasterxml/Hymanson/annotation/JsonManagedReference.html):
用于指示被注释的属性是字段之间双向链接的一部分的注释;并且它的作用是“父”(或“转发”)链接。属性的值类型(类)必须有一个用 JsonBackReference 注释的兼容属性。链接的处理使得用这个注解注解的属性得到正常处理(正常序列化,反序列化没有特殊处理);它是需要特殊处理的匹配反向引用
JsonBackReference:(https://fasterxml.github.io/Hymanson-annotations/javadoc/2.5/com/fasterxml/Hymanson/annotation/JsonBackReference.html):
用于指示关联属性是字段之间双向链接的一部分的注解;并且它的作用是“子”(或“后”)链接。属性的值类型必须是 bean:不能是 Collection、Map、Array 或枚举。处理链接使得使用此注释注释的属性不会被序列化;并且在反序列化期间,它的值被设置为具有“托管”(前向)链接的实例。
Example:
例子:
Owner.java:
所有者.java:
@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;
Car.java:
汽车.java:
@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;
Another solution is to use @JsonIgnore
which will just set null to the field.
另一种解决方案是使用@JsonIgnore
which 将只为该字段设置 null 。