4

什么时候会StackOverError抛出?

或者更确切地说,它什么时候不会被抛出?

例如,如果我们使用原始运算符+, +=, -, -=, == <, >, /,%等:

try {
     // operations +, +=, -, -=, == <, >, /, %, etc
} catch (java.lang.StackOverflowError e) {
     // will never occur?
}

有什么保证StackOverflowError不会被抛出吗?

4

5 回答 5

4

+理论上,可以通过添加递归循环在内部使用递归来实现一些奇怪的 JVM运算符+ 1。其他运算符也可以使用内部方法调用来实现。

我认为永远不会是这样。在每个典型的 JVM/架构中,这些操作都是使用单个操作/指令实现的。所有这些运算符都有字节码指令,我希望它们被 1:1 转换为汇编。但是 JLS 中没有任何保证。

顺便说一下JavaDoc:

当由于应用程序递归太深而发生堆栈溢出时引发。

是不正确的。您StackOverflowError无需任何递归即可获得 - 如果您有非常深的调用树并且方法有很长的参数列表。然而,这实际上很难实现。

于 2012-02-13T13:23:58.900 回答
4

StackOverflowErrorJava 语言规范中唯一的参考如下

15.12.4.5 创建帧、同步、传输控制

m某个类中的方法S已被标识为要调用的方法。

现在创建了一个新的激活框架,其中包含目标引用(如果有)和参数值(如果有),以及用于局部变量和堆栈的足够空间以供调用的方法以及任何其他可能的簿记信息实施所需的[...]。如果没有足够的可用内存来创建这样的激活帧,StackOverflowError则会抛出 an。

JVM 规范说明如下:

StackOverflowError:Java 虚拟机实现已用完线程的堆栈空间,这通常是因为线程正在执行无限数量的递归调用,因为正在执行的程序中出现错误。

所以,从上面的说法来看...

我想知道不调用任何函数的代码是否永远不会抛出 java.lang.StackOverflowError?

...是的,这是真的。

例如,如果我在原语(包括 long 和 double)上使用运算符+, +=, -, -=, ==, <, >,等/%

对。这些都不会(自己)调用方法,因此不应导致StackOverflowError.

于 2012-02-13T13:25:05.970 回答
2

请参阅文档:

当由于应用程序递归太深而发生堆栈溢出时引发。

因此,当您的应用程序根本不递归(即不调用方法)时,您将不会得到StackOverflowError.

当然,当我们不只讨论素数(基本操作直接使用 Java 字节码指令实现)时,我们很容易遇到StackOverflowErrors.

样本:

int foo = 23;

富 = 23 + 酒吧;

如果barjava.lang.Integer怎么办?Java 将进行自动拆箱,这将导致以下字节码:

   0:双向推 23
   2:istore_1
   3:双推 23
   5:获取静态#3;//字段栏:Ljava/lang/Integer;
        vvvvvv
   8:调用虚拟#4;//方法java/lang/Integer.intValue:()I
        ^ ^ ^ ^ ^ ^ ^
   11:添加
   12:istore_1
   13:返回

这是一个(隐式)方法调用,因此可能导致 StackOverflow。

于 2012-02-13T13:20:49.560 回答
2

例如,如果我在原语(包括和)上使用运算符+, +=, -, -=, == <, >,/等...我们可以保证不会从该操作中引发 stackoverflow 错误吗?%longdouble

是的,对于标准数学和比较运算符。关键是您所说的“...关于原语...”由于 Java 不允许运算符重载,并且 JVM 对这些原语的实现不会涉及递归,因此您可以确定。如果您谈论的是非基元,则不一定是这种情况,其中某些运算符可能会导致调用非 JVM 代码(+例如,用于将对象附加到字符串,这将触发对象的toString方法) .

于 2012-02-13T13:25:14.707 回答
0

不调用任何函数的代码真的永远不会抛出一个java.lang.StackOverflowError?

一个StackOverflowError 是一个 VirtualMachineError。事实证明没有VirtualMachineError关于s 的不抛出保证。Java 虚拟机规范说明了以下内容(添加了重点)。

本规范无法预测可能会遇到内部错误或资源限制的位置,也没有明确规定何时可以报告它们。因此,下面定义的任何 VirtualMachineError 子类都可能在 Java 虚拟机运行期间随时抛出: ...StackOverflowError

于 2012-02-14T13:15:16.283 回答