Question

When will a StackOverError be thrown?

Or rather, when will it not be thrown?

For example, if we use the primitive operators +, +=, -, -=, == <, >, /, %, etc:

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

Is there any guarantee that StackOverflowError will not be thrown?

Was it helpful?

Solution

is it true that code which do not call any functions will never throw a java.lang.StackOverflowError?

A StackOverflowError is-a VirtualMachineError. It transpires that there are no no-throw guarantees about VirtualMachineErrors. The Java Virtual Machine Specification says the following (emphasis added).

This specification cannot predict where internal errors or resource limitations may be encountered and does not mandate precisely when they can be reported. Thus, any of the VirtualMachineError subclasses defined below may be thrown at any time during the operation of the Java virtual machine: ... StackOverflowError

OTHER TIPS

In theory, on some weird JVM + operator can be implemented using recursion internally by adding + 1 in a recursive loop. The other operators might also be implemented using internal method call.

I don't think it will ever be the case. In every typical JVM/architecture these operations are implemented using single operation/instruction. There are bytecode instructions for all these operators and I would expect they are translated 1:1 to assembly. But there are no guarantees in the JLS.

By the way the JavaDoc:

Thrown when a stack overflow occurs because an application recurses too deeply.

is not really correct. You can get StackOverflowError without any recursion - if you have very deep call tree and methods have very long argument list. However this is very hard to achieve in practical terms.

The only reference to StackOverflowError in the Java Language Specification is the following:

15.12.4.5 Create Frame, Synchronize, Transfer Control

A method m in some class S has been identified as the one to be invoked.

Now a new activation frame is created, containing the target reference (if any) and the argument values (if any), as well as enough space for the local variables and stack for the method to be invoked and any other bookkeeping information that may be required by the implementation [...]. If there is not sufficient memory available to create such an activation frame, an StackOverflowError is thrown.

The JVM spec says the following:

StackOverflowError: The Java virtual machine implementation has run out of stack space for a thread, typically because the thread is doing an unbounded number of recursive invocations as a result of a fault in the executing program.

So, judging from the above statements...

I was wondering is it true that code which do not call any functions will never throw a java.lang.StackOverflowError?

...yes, that's true.

For example, if I use the operators +, +=, -, -=, ==, <, >, /, % etc on primitives (including long and double),

Right. None of those will ever (by themselves) invoke a method and should therefore not cause a StackOverflowError.

For example, if I use the operators +, +=, -, -=, == <, >, /, % etc on primitives (including long and double)...Can we can guarantee there's no way a stackoverflow error would be thrown from that operation?

Yes, for the standard math and comparison operators. The key there was where you said "...on primitives..." Since Java doesn't allow operator overloading, and the JVM's implementation of these for primitives will not involve recursion, you can be sure. This would not necessarily be the case if you were talking about non-primitives, where certain of these operators might cause a call to non-JVM code (using + to append an object to a string, for instance, which would trigger the object's toString method).

See the documentation:

Thrown when a stack overflow occurs because an application recurses too deeply.

So, when your application does not recurse at all (i.e. does not call methods), you won't get a StackOverflowError.

Of course, when we do not talk about primities only (where the basic operations are implemented directly using Java bytecode instructions), we easily run into StackOverflowErrors.

Sample:

int foo = 23;

foo = 23 + bar;

What if bar is an java.lang.Integer? Java will do automatic unboxing and that will lead to the following bytecode:

   0:   bipush  23
   2:   istore_1
   3:   bipush  23
   5:   getstatic   #3; //Field bar:Ljava/lang/Integer;
        v v v v v v v 
   8:   invokevirtual   #4; //Method java/lang/Integer.intValue:()I
        ^ ^ ^ ^ ^ ^ ^
   11:  iadd
   12:  istore_1
   13:  return

That is a (implicit) method invokation and could therefore cause a StackOverflow.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top