In Java, is there a way to know that a StackOverflow
error or OutOfMemory
exception may happen soon?
The OutOfMemory
exception m
You can anticipate out-of-memory conditions with Runtime.freeMemory() and Runtime.maxMemory(). Most times it'll be hard recovering gracefully, but I leave that to you.
Most StackOverflow errors come out of bad recursion. Unfortunately, the problem of determining if a recursion will stop is generally not decidable (this is a central concept in CS). There are cases, however, you could get warnings, for example some IDEs will let you know if you're invoking a function recursively with no parameters.
The MemoryMXBean can emit notifications if your memory reaches a certain threshold.
I'm surprised I didn't see this mentioned in the other posts, but you can use ManagementFactory in Java 5/6 to get at a lot of the memory usage information.
Look at the platform mbean server page for more information on detecting low memory conditions in Java. I believe you can setup notifiers to call code when memory usage reaches a certain threshold.
You could discover a lot about recursion depth, by creating a Throwable object, and querying its getStackTrace() method. But this is expensive to do.
If you really have a method with a small potential of throwing a StackOverflowError or an OutOfMemoryError why not just insert try-catch blocks and catch those errors? They can be caught and handled just like checked exceptions.
Usually memory useage is hard to predict.
Stack Overflows from infinite regression generally show up in the write/debug cycle.
Harder to catch are memory issues on things like large held collections, caches, etc.etc. As has been pointed out you can check runtime free and max memory, but be careful, as their meanings aren't obvious - "free" here, means "free now", e.g. meaning if you ran a full gc you might get more. Unfortunately there's no way to get the "total possible free, including garbage-collectible" without running System.gc(), which is not a nice thing to do on a production application (where you're liable to have large enough data sets to cause the problem in the first place) because the entire JVM will come to a screeching halt for a few seconds (or more, in a large app). Note that even System.gc() is not guaranteed to run "now", but my experience has been that it has whenever I've played with it.
You can print gc activity from the running jvm by starting java with -verbose:gc, -XX:+PrintGCTimeStamps, and -XX:+PrintGCDetails (more detail here), and in general if the collector starts to run more frequently, it's probably a sign that you're running out of memory.