236

I've looked everywhere and can't find a solid answer. According to the documentation, Java throws a java.lang.StackOverflowError error under the following circumstance:

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

But this raises two questions:

  • Aren't there other ways for a stack overflow to occur, not only through recursion?
  • Does the StackOverflowError happen before the JVM actually overflows the stack or after?

To elaborate on the second question:

When Java throws the StackOverflowError, can you safely assume that the stack did not write into the heap? If you shrink the size of the stack or heap in a try/catch on a function that throws a stack overflow, can you continue working? Is this documented anywhere?

Answers I am not looking for:

  • A StackOverflow happens because of bad recursion.
  • A StackOverflow happens when the heap meets the stack.
hichris123
  • 10,145
  • 15
  • 56
  • 70
retrohacker
  • 3,194
  • 4
  • 21
  • 31
  • 1
    The default stack size is quite large, AFAIK 8 MB on Linux. That makes it unlikely to produce a stack overflow without recursion. – nosid Mar 04 '14 at 20:49
  • 1
    You could produce a gigantic chain of method calls which would cause a SO (like method a calling b, b calling c, c calling d, ...), but it is purely imaginative. – Smutje Mar 04 '14 at 20:50
  • @nosid yes, but you can change the default stack and heap size using `-Xms` `-Xmx`, I don't know an incredible amount about the garbage collector, can manipulating these values cause a stackoverflow (or I guess out of memory error since we are now talking about the heap) in weird situations? – retrohacker Mar 04 '14 at 20:53
  • 8
    http://codegolf.stackexchange.com/questions/9359/shortest-program-that-throws-stackoverflow-error contains a few stackoverflow producing programs, including a few in java, all using a form or another of recursion. – njzk2 Mar 04 '14 at 22:02
  • @Crackers squashing down -Xmx too far can cause a "heap overflow" (OutOfMemoryError, popularly called "OOME"), yes. Doesn't take any more "weirdness" than setting silly settings. – jackr Mar 05 '14 at 00:42
  • @jackr Can something similar happen with -Xms? – retrohacker Mar 05 '14 at 01:30
  • @Crackers -Xms is an odd duck. Since it only defines the starting heap size, and has no implication for maximum size, you'd think the worst it could do would be to slow things down while the JVM grows the heap to a more reasonable size. But ISTR running into bigger problems, Error or Exception throwing problems, due to too-small -Xms. But it was a long time ago: I can't recall details, I'd probably recall them wrong anyway, and besides the JVM's probably been fixed :D – jackr Mar 05 '14 at 01:56
  • In c you could use large stack allocated objects. – CodesInChaos Mar 05 '14 at 09:07
  • check [this answer](http://stackoverflow.com/a/21724714/1686291) to differentiate SO and OutOfMemoryError... – Not a bug Mar 05 '14 at 11:54
  • @jackr is there any particular reason you abbreviated "I seem to recall"? Kind of an unnecessary/esoteric abbreviation, to be honest. – TylerH Mar 05 '14 at 18:27
  • 1
    Stacks running into heap? That would be the 1980th before memory management units became common in CPUs. ;-) – Martin Mar 05 '14 at 20:07
  • Not looking for answers like "infinite recursion" is a bit silly, since that is **by far** the most common reason which could conceivably happen. Otherwise, it is really, really hard to get a stack overflow with a reasonable program of any kind (yes... you _can_ provoke it if you want to prove a point, but it doesn't just happen by accident). – Damon Mar 05 '14 at 22:32
  • @TylerH Sorry if my abbreviation was unclear. I thought it was lingua franca. – jackr Mar 06 '14 at 00:15
  • @njzk2 See also http://codegolf.stackexchange.com/questions/21114/weirdest-way-to-produce-a-stack-overflow for many examples with *and* without recursion. – Jason C Mar 06 '14 at 03:04
  • 1
    *"A StackOverflow happens when the heap meets the stack."* -- Well, you see, @Crackers, when a heap and a stack fall in love... – Jason C Mar 06 '14 at 03:09
  • @Damon In Java — In Pascal like languages (or a modern C — read up alloca) where large objects are created on the stack you can easily fill the stack without recursion. – Martin Mar 06 '14 at 05:31
  • @jackr I spent like 30 seconds trying to think of what language that could be before I realized what you were saying :-( – TylerH Mar 06 '14 at 07:32
  • @Martin: That is what I'm saying with "if you try to prove a point". Of course I can trivially `alloca` 20 megabytes, or create an array of 100 million integers with automatic storage, but other than me doing unreasonable stuff (not everything that is syntactically valid _is valid_ or _is reasonable_) what does that really prove? In a reasonable program, stack usage is maybe a hundred kilobytes. When that isn't the case, 99.9% of the time it's a program error such as infinite recursion. – Damon Mar 06 '14 at 11:12
  • It occurs when the stack overflows, i.e. to many pushes, not enough pops. – Jodrell Mar 06 '14 at 12:10
  • @JasonC : In these examples, the only one that do not use recursion are those in C or in weird languages. All those in java use a form of more or less direct recursion. – njzk2 Mar 06 '14 at 13:49

10 Answers10

197

It seems you're thinking that a stackoverflow error is like a buffer overflow exception in native programs, when there is a risk of writing into memory that had not been allocated for the buffer, and thus to corrupt some other memory locations. It's not the case at all.

JVM has a given memory allocated for each stack of each thread, and if an attempt to call a method happens to fill this memory, JVM throws an error. Just like it would do if you were trying to write at index N of an array of length N. No memory corruption can happen. The stack can not write into the heap.

A StackOverflowError is to the stack what an OutOfMemoryError is to the heap: it simply signals that there is no more memory available.

Description from Virtual Machine Errors (§6.3)

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.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 26
    Just a appointment, java.lang.StackOverflowError is an Error, like OutOfMemory, and is not a Exception. Error and Exception extends Thowable. Its a really bad praticce to catch a Error/throwable instead a Exception. – Ezequiel Mar 04 '14 at 20:55
  • 1
    renamed exception to error. Thanks. – JB Nizet Mar 04 '14 at 20:57
  • Needs to answer the first question `Aren't there other ways for a stack overflow to occur, not only through recursion?` – retrohacker Mar 04 '14 at 21:14
  • 2
    You got your answer in all the other answers. You get the error when the stack is full, whatever the way you get to this situation. But I've never seen that happen without recursion, given the large size of the stack. – JB Nizet Mar 04 '14 at 21:21
  • 2
    HotSpot has reliable and safe stack overflow detection, but I wonder if such behavior is mandated by the JVM spec? – ntoskrnl Mar 04 '14 at 22:22
  • 4
    @ntoskrnl: yes: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2 – JB Nizet Mar 04 '14 at 22:30
54

Aren't there other ways for a stack overflow to occur, not only through recursion?

Sure. Just keep calling methods, without ever returning. You'll need a lot of methods, though, unless you allow recursion. Actually, it doesn't make a difference: a stack frame is a stack frame, whether it is one of a recursive method or not is the same.

The answer to your second question is: The stackoverflow is detected when the JVM tries to allocate the stack frame for the next call, and finds it is not possible. So, nothing will be overwritten.

Ingo
  • 36,037
  • 5
  • 53
  • 100
  • I thought stack overflows were based on on a fixed "recursion depth". If its simply because there's no memory available, it should just be an OOME I think. – Cruncher Mar 04 '14 at 21:45
  • 1
    @Cruncher It's not a fixed depth. The arguments of the methods, for example, are stored on the stack. More arguments mean more memory needed for them on the stack, which means a smaller depth before the memory allocated for the stack is exhausted. Test it with a method calling itself with 1 argument, then with 5 for example. – JB Nizet Mar 04 '14 at 22:07
  • Exactly, @JBNizet. ALso, the JVM knows how much stack the bytecode will need in addition to any arguments. One can see this with `javap` – Ingo Mar 04 '14 at 22:34
  • 3
    Note that a JVM may choose to use a fixed depth, or may choose to dynamically expand the stack space, as per the spec. Hotspot doesn't do it, at least by default. See http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2 – JB Nizet Mar 04 '14 at 22:35
  • 1
    @Ingo the bytecode stack is somewhat distinct from the stack used at runtime for method calls. The runtime compiles the bytecode to native code (or at least is free to do so) and when it does so at least some of the stack usage there is translated to machine register usage. It may reserve some stack space for temporary storage, but this is often less than the maximum amount of bytecode interpretation stack required. – Jules Mar 05 '14 at 08:09
  • The way I see it, there are two good ways to intentionally generate an SO error without recursion: call some really big functions (say, a bunch of functions with 255 doubles as parameters or otherwise a ton of local variables). It will take a while. Or take the opposite route: allocate something gigantic on the heap (e.g. the mother of all arrays) to intentionally bring you juuust below the memory limit, then call a function. This is one case where a sufficiently bright optimizer can screw your efforts, though. – Linear Mar 05 '14 at 10:36
  • 2
    @Jsor actually, the java heap and stack do not interfere. You can get stack overflow even when you have terabytes free in the heap. Conversely, you can die of OutOfMemory, without your stack getting smaller or something. – Ingo Mar 05 '14 at 11:55
  • @Ingo huh, I guess I just assumed Java used the model where the stack and heap were allocated on opposite ends and grew towards each other. – Linear Mar 05 '14 at 20:58
  • 3
    @Jsor A java app can have multiple threads, which share a heap, but each of them has a separate stack space. So this wouldn't work that easily. – Paŭlo Ebermann Mar 05 '14 at 21:34
  • What about a method that has an insane number of primitive-typed local variables? – Evan Plaice Mar 07 '14 at 22:09
  • @EvanPlaice the more variables you have, the bigger the stack frame will be, the sooner SO will occur. Same goes for method parameters. However, I guess the compiler is smart enough to not allocate space for variables you don't actually use. – Ingo Mar 30 '17 at 23:33
27

Aren't there other ways for a stack overflow to occur, not only through recursion?

Challenge accepted :) StackOverflowError without recursion (challenge failed, see comments):

public class Test
{
    final static int CALLS = 710;

    public static void main(String[] args)
    {
        final Functor[] functors = new Functor[CALLS];
        for (int i = 0; i < CALLS; i++)
        {
            final int finalInt = i;
            functors[i] = new Functor()
            {
                @Override
                public void fun()
                {
                    System.out.print(finalInt + " ");
                    if (finalInt != CALLS - 1)
                    {
                        functors[finalInt + 1].fun();
                    }
                }
            };
        }
        // Let's get ready to ruuuuuuumble!
        functors[0].fun(); // Sorry, couldn't resist to not comment in such moment. 
    }

    interface Functor
    {
        void fun();
    }
}

Compile with standard javac Test.java and run with java -Xss104k Test 2> out. After that, more out will tell you:

Exception in thread "main" java.lang.StackOverflowError

Second try.

Now the idea is even simpler. Primitives in Java can be stored on the stack. So, let's declare a lot of doubles, like double a1,a2,a3.... This script can write, compile and run the code for us:

#!/bin/sh

VARIABLES=4000
NAME=Test
FILE=$NAME.java
SOURCE="public class $NAME{public static void main(String[] args){double "
for i in $(seq 1 $VARIABLES);
do
    SOURCE=$SOURCE"a$i,"
done
SOURCE=$SOURCE"b=0;System.out.println(b);}}"
echo $SOURCE > $FILE
javac $FILE
java -Xss104k $NAME

And... I got something unexpected:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f4822f9d501, pid=4988, tid=139947823249152
#
# JRE version: 6.0_27-b27
# Java VM: OpenJDK 64-Bit Server VM (20.0-b12 mixed mode linux-amd64 compressed oops)
# Derivative: IcedTea6 1.12.6
# Distribution: Ubuntu 10.04.1 LTS, package 6b27-1.12.6-1ubuntu0.10.04.2
# Problematic frame:
# V  [libjvm.so+0x4ce501]  JavaThread::last_frame()+0xa1
#
# An error report file with more information is saved as:
# /home/adam/Desktop/test/hs_err_pid4988.log
#
# If you would like to submit a bug report, please include
# instructions how to reproduce the bug and visit:
#   https://bugs.launchpad.net/ubuntu/+source/openjdk-6/
#
Aborted

It's 100% repetitive. This is related to your second question:

Does the StackOverflowError happen before the JVM actually overflows the stack or after?

So, in case of OpenJDK 20.0-b12 we can see that JVM firstly exploded. But it seems like a bug, maybe someone can confirm that in comments please, because I'm not sure. Should I report this? Maybe it's already fixed in some newer version... According to JVM specification link (given by JB Nizet in a comment) JVM should throw a StackOverflowError, not die:

If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.


Third try.

public class Test {
    Test test = new Test();

    public static void main(String[] args) {
        new Test();
    }
}

We want to create new Test object. So, its (implicit) constructor will be called. But, just before that, all the members of Test are initialized. So, Test test = new Test() is executed first...

We want to create new Test object...

Update: Bad luck, this is recursion, I asked question about that here.

Community
  • 1
  • 1
Adam Stelmaszczyk
  • 19,665
  • 4
  • 70
  • 110
  • 11
    How is it not recursive? fun() calls fun(). On a different object, but that's still recursive. – JB Nizet Mar 04 '14 at 21:23
  • So if I understand this code fully, you create an array of 710 objects that each have a method `fun()`, each object in the array calls the method of the next object? – retrohacker Mar 04 '14 at 21:23
  • 1
    @Crackers. Except the last one, exactly. – Adam Stelmaszczyk Mar 04 '14 at 21:24
  • 3
    @JBNizet But fun() calls different fun(), with different `finalInt` "closed" object, so it's not recursion. – Adam Stelmaszczyk Mar 04 '14 at 21:25
  • 17
    No. There's a single `fun()` method being called, on different instances of the same class. That's recursion. – JB Nizet Mar 04 '14 at 21:27
  • @JBNizet You are more experienced than me, I believe you're right. Could you please explain what happens exactly with that `finalInt`? It is somehow added to each anonymous object probably, but how? As a private member for example? – Adam Stelmaszczyk Mar 04 '14 at 21:40
  • 1
    Yes. The generated class has 2 implicit members: one referencing the outer Test instance, and one containing the value of the final int. They're passed as arguments of the constructor generated for the inner class. Use `javap 'Test$1'` to look at the generated inner class. – JB Nizet Mar 04 '14 at 21:42
  • @JBNizet Great, thanks, I didn't know that. Ok, so I failed the challenge. Maybe you have an idea for a code that will produce SO without recursion (except hard-coding 710 methods by hand)? Maybe using reflection? – Adam Stelmaszczyk Mar 04 '14 at 21:50
  • Frankly, I don't feel like inventing a contrived example showing that it's possible. In real life, I've never seen it happen without recursion, because the stack is large enough to cover all the reasonable cases not involving recursion. Even with giant stacks involving a lot of method interceptors. – JB Nizet Mar 04 '14 at 21:54
  • 2
    @AdamStelmaszczyk You could write a code generator to do it. Then compile the result of that and run it. – Brian Rogers Mar 04 '14 at 22:54
  • 5
    @Adam Write a native JNI function that allocates a gigantic object on the stack and then call a Java method. – Voo Mar 04 '14 at 23:42
  • I would think the Java compiler should be able to apply tail-call optimization to that, which would make it not overflow? – Rawler Mar 05 '14 at 09:12
  • @Rawler Scala does to tail-call optimisation but in Java it is not guaranteed. Some compiler do (IBM) others don't (Sun). Also some JVMs do tail-call optimisation as part of the JIT compilation (JRockit). Others don't (HotSpot). — If you want to do functional programming use a langauge designed for it. i.E. Scala. {Everything in () AFASIK and I might know wrong} – Martin Mar 05 '14 at 20:16
  • 4
    Huh, yup you definitely found a bug there. Basically as long as you don't write faulty native code and invoke it per JNI (at least indirectly) you should never see one of those error messages. Have to check if that bug still works on the latest release. – Voo Mar 06 '14 at 01:59
  • 2
    Checked with `OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)` and after increasing the stack size to 228k (minimal size it allows for me) and generating 10k variables I do get the expected StackOverflowError, so the bug's been fixed. – Voo Mar 06 '14 at 02:04
  • 1
    @AdamStelmaszczyk You may be interested in http://codegolf.stackexchange.com/questions/21114/weirdest-way-to-produce-a-stack-overflow, the answers there contain many examples of causing stack overflows, in many languages, and many times without recursion. With Java, because of the robustness of the JVM spec, I believe the only way to fill the stack without recursion is to have an inordinately high number of method parameters and local variables sitting around. – Jason C Mar 06 '14 at 03:07
  • @AdamStelmaszczyk I am using Java 8 and my JVM does not crash. i get the output as 0.0 – Jatin Mar 11 '14 at 06:46
3

There is no "StackOverFlowException". What you mean is "StackOverFlowError".

Yes you can continue working if you catch it because the stack is cleared when you do that but that would be a bad and ugly option.

When exactly the error is thrown ? - When you call a method and the JVM verifies if there is enough memory to do it. Of course, the error is thrown if it's not possible.

  • No, that is the only way you can get that error: getting your stack full. But not only through recursion, also calling methods that infinitely call other methods. It's a very specific error so no.
  • It is thrown before the stack is full, exactly when you verify it. Where would you put the data if there is no space available ? Overriding others ? Naah.
GabrielBB
  • 2,479
  • 1
  • 35
  • 49
  • 1
    Would not have asked and done research if I could answer it myself. I understand that this is typically a result of a recursive function, which is why I addressed this point in the question itself, and explicitly stated this is not the answer I was looking for. Are there situations in which you can predict a stackoverflow may occur due to memory constraints, but this isn't necessarily a fatal problem? What are the two bullet points at the end? I don't follow what they are saying. – retrohacker Mar 04 '14 at 21:19
  • There are no realistic circumstances where you can assume you are "safe" after catching a StackOverflowError. The problem is not the JVM's health, but rather the health of your own data and operations, and is complicated because you can't predict and plan for exactly when and where the Error is raised--hence, which of your code has or has not executed. – jackr Mar 05 '14 at 00:52
  • 3
    There are plenty of circumstances, for example with a recursive algorithm that only modifies a limited set of data. In that case you can ditch those results and handle the failure however you like. – Tim B Mar 05 '14 at 13:56
3

There are two main places that things can be stored in Java. The first is the Heap, that's used for dynamically allocated objects. new.

In addition each running thread gets its own stack, and it gets an amount of memory allocated to that stack.

When you call a method then data is pushed into the stack to record the method call, the parameters being passed in, and any local variables being allocated. A method with five local variables and three parameters will use more stack space than a void doStuff() method with no local variables will.

The main advantages of the stack are that there is no memory fragmentation, everything for one method call is allocated on the top of the stack, and that returning from methods is easy. To return from a method you just unwind the stack back to the previous method, set any value needed for the return value and you are done.

Because the stack is a fixed size per thread, (note that the Java Spec does not require a fixed size, but most JVM implementations at the time of writing use a fixed size) and because space on the stack is needed whenever you make a method call hopefully it should now be clear why it can run out and what can cause it to run out. There isn't a fixed number of method calls, there isn't anything specific about recursion, you get the exception which you try to call a method and there isn't enough memory.

Of course the size of stacks is set high enough that it is highly unlikely to happen in regular code. In recursive code though it can be quite easy to recurse to huge depths, and at that point you start running into this error.

Tim B
  • 40,716
  • 16
  • 83
  • 128
  • Nice summary but note that the stack size does not need to be fixed, see [this comment by JB Nizet](http://stackoverflow.com/questions/22182669/what-actually-causes-a-stack-overflow-error#comment33674179_22182840). – siegi Mar 12 '14 at 17:56
  • @siegi Thanks, I've added a note to clarify that. – Tim B Mar 14 '14 at 09:07
3

The most common cause of StackOverFlowError is excessively deep or infinite recursion.

For instance:

public int yourMethod(){
       yourMethod();//infinite recursion
}

In Java:

There are two areas in memory the heap and stack. The stack memory is used to store local variables and function call, while heap memory is used to store objects in Java.

If there is no memory left in stack for storing function call or local variable, JVM will throw java.lang.StackOverFlowError

while if there is no more heap space for creating object, JVM will throw java.lang.OutOfMemoryError

AmitG
  • 10,365
  • 5
  • 31
  • 52
Lazy Coder
  • 307
  • 4
  • 12
2

StackOverflowError occurs due to an application recurses too deeply (This is not an answer you are expecting).

Now other things to happen to StackOverflowError is keep calling methods from methods till you get StackOverflowError, but nobody can program to get StackOverflowError and even if those programmer are doing so then they are not following coding standards for cyclomatic complixity that every programmer has to understand while programming. Such reason for 'StackOverflowError' will require much time to rectify it.

But unknowingly coding one line or two line which causes StackOverflowError is understandable and JVM throws that and we can rectify it instantly. Here is my answer with picture for some other question.

Community
  • 1
  • 1
AmitG
  • 10,365
  • 5
  • 31
  • 52
0

A StackOverflow happens when a function call is made and the stack is full.

Just like an ArrayOutOfBoundException. It cannot corrupt anything, in fact it is very possible to catch it and recover from it.

It usually happens as the result of an uncontrolled recursion, but it can also be caused by simply have a very deep stack of functions call.

njzk2
  • 38,969
  • 7
  • 69
  • 107
  • 1
    This is wrong. A StackOverflowError is nothing like an ArrayOutOfBoundException. It's not even an Exception at all! It can absolutely corrupt things. If you call some recursive function, and it throws back a StackOverflowError you can make no assumptions about the correctness of the state of any objects that it touched anymore. It may have done only part of an operation. It's generally a bad idea to try to recover from this, unless you have a very good reason, and know what you're doing. – Cruncher Mar 04 '14 at 21:48
  • Consider a quick sort that stack overflowed. When the stack overflows the array can be in no real logical order. The array has been corrupted. – Cruncher Mar 04 '14 at 21:50
  • 5
    This is a comparison. SO in not an AOOBE, but it can be compared to one because basically you are trying to add an element to a stack that is full. As for the corruption of thing, the execution is stopped at a very precise point, just like with any other error. In itself it will not write stuff in the heap, which is the sense of the question (`can you safely assume that the stack did not write into the heap?`) – njzk2 Mar 04 '14 at 21:53
  • It is possible to catch it, and to recover from it. It is not necessarily easy, but doable. – njzk2 Mar 04 '14 at 21:58
  • 5
    @Cruncher: Is there any reason why a StackOverFlowError from QuickSort would be more likely to leave the array with duplicate and missing items than would be any other kind of exception (e.g. objects containing items are compared based upon the average value of the items, and one of the objects has no items and throws `DivisionByZeroException`.)? Either the sort maintains the invariant that the array always holds a permutation whenever the comparer function is called, or it doesn't. – supercat Mar 04 '14 at 22:01
  • A sort that includes a swap (tmp = a[i]; a[i]=a[j]; a[j]=tmp;) has a moment when the array contains no references to a[i]. If a is static (likely) and tmp is not (also likely), then a SOE at that moment would leave the array missing one element, and with two references to another element. Your program logic would very likely consider that "corruption." But you might need more code in the critical zone to trigger the Error. – jackr Mar 05 '14 at 02:05
  • @jackr : a swap is quite unlikely to cause a stackoverflow, as there is no method called during this process. I think it should be considered an atomic operation. – njzk2 Mar 05 '14 at 14:03
  • @njzk2 In any case you're basing a lot of stuff on assumptions. You have to analyse your methods to see what can happen if a StackOverflow happens. Analysing all cases is often not worth it. The statement: "It **cannot** corrupt anything"(emphasis mine) is simply incorrect. – Cruncher Mar 06 '14 at 14:13
  • 1
    @Cruncher : you can emphasis all you want, I still disagree. There is no corruption in the sense the SO intends it. I requote again `can you safely assume that the stack did not write into the heap?` => `Yes` – njzk2 Mar 06 '14 at 15:17
  • @Cruncher: Just another point of view: Each and every error handling code needs to be very careful with assumptions it makes about the failing code. There is nothing "special" about a `StackOverflowError` from this perspective. E.g. consider an `SQLException`: The caller of a method accessing a database might not know if some operation was successfully written to the database or not if an `SQLException` has been thrown by the called method: The operation might have been committed but closing the database connection threw the exception. You need to know what you can safely assume and what not. – siegi Mar 12 '14 at 17:50
  • @siegi I agree. But StackOverflowError can happen at *any* method call. SQLException can only happen when thrown. You can narrow down on the cases for SQLException in a way that is often not possible with StackOverflowError – Cruncher Mar 12 '14 at 17:53
  • If you go there, a `RuntimeException` can happen at any moment. – njzk2 Mar 12 '14 at 17:54
  • @njzk2 And I wouldn't suggest people to try to handle them, unless you've subclassed it and thrown it yourself. – Cruncher Mar 12 '14 at 17:55
  • neither would I. I just say it is possible. Just like you can catch an `OutOfMemoryError`. – njzk2 Mar 12 '14 at 17:57
  • @njzk2 Nobody is suggesting that its impossible. Just that the statement "it cannot corrupt anything" is false. You have to be very careful, just as you would with OOME. This is why they make them errors – Cruncher Mar 12 '14 at 18:30
  • @Cruncher: I don't want to push the discussion even further, so this is my last comment here: Of course you are right, but you can certainly assume the `StackOverflowError` was thrown from somewhere within a specific `try` block, else you wouldn't be able to catch it. If you discard any data used/produced by the `try` block (for example to restart the calculation with some smaller parameter or whatever) you would be safe, if I don't miss anything. To summarize: Yes a `StackOverflowError` can "absolutely corrupt things", but it breaks at most the data processed, not e.g. the state of the JVM… – siegi Mar 12 '14 at 18:34
  • @Cruncher: This is starting to go in circle. The definition of `corruption` in the scope of this question is quite clearly defined by @Crackers. – njzk2 Mar 12 '14 at 18:52
0

In c# you can achieve stack overflow in a different manner, by wrongly defining object properties. For example :

private double hours;

public double Hours
        {
            get { return Hours; }
            set { Hours = value; }
        }

As you can see this will forever keep on returning Hours with an uppercase H , which in itself will return Hours and so and so on.

A stack overflow will often occur also because of running out of memory or when using managed languages because your language manager (CLR, JRE) will detect that your code got stuck in an infinite loop.

-1

But this raises two questions:

  1. Aren't there other ways for a stack overflow to occur, not only through recursion?
  2. Does the StackOverflowError happen before the JVM actually overflows the stack or after?
  1. It can also occur when we are Allocating size greater than stack's limit (for eg. int x[10000000];).

  2. Answer to second is

Each thread has its own stack that holds a frame for each method executing on that thread. So the currently executing method is at the top of the stack. A new frame is created and added (pushed) to the top of stack for every method invocation. The frame is removed (popped) when the method returns normally or if an uncaught exception is thrown during the method invocation. The stack is not directly manipulated, except to push and pop frame objects, and therefore the frame objects may be allocated in the Heap and the memory does not need to be contiguous.

So by considering stack in a Thread we can conclude.

A stack can be a dynamic or fixed size. If a thread requires a larger stack than allowed a StackOverflowError is thrown. If a thread requires a new frame and there isn’t enough memory to allocate it then an OutOfMemoryError is thrown.

you can get description for JVM here

eatSleepCode
  • 4,427
  • 7
  • 44
  • 93
  • 4
    Not in Java. int x[10000000] is allocated on the heap. – Jeremy Stein Mar 05 '14 at 19:48
  • @JeremyStein I have read it here [here](http://www.roseindia.net/javatutorials/stack_overflow.shtml) isn't that correct? – eatSleepCode Mar 06 '14 at 05:00
  • @JeremyStein int is primitive type and it gets memory on stack. You can check it here http://programmers.stackexchange.com/questions/65281/stack-and-heap-memory-in-java – eatSleepCode Mar 06 '14 at 05:08
  • I believe an `OutOfMemoryError` is thrown when the heap is full. A `StackOverflowError`, however is thrown when a thread requires an additional frame when there is no room for it. (This is confirmed by comments and answers on this page). – 11684 Mar 06 '14 at 09:50
  • @eatSleepCode, the [roseindia page](http://www.roseindia.net/javatutorials/stack_overflow.shtml) is mistaken. That's not even legal Java. You have to write int[] x = new int[10000000]; – Jeremy Stein Mar 06 '14 at 17:32