Related
I've been watching Douglas Schmidt classes on Parallel Java. He introduces Lambda x method referencing syntax discussion, highlighting how the last one is preferable, as it makes clearer what the code is actually doing, not what the programmer is trying to do with the code, even more than forEach approach.
String[] names = {"first", "Second", "third"};
Arrays.sort(names, (n1,n2) -> n1.compareToIgnoreCase(n2));
Arrays.sort(names, String::compareToIgnoreCase); //preferable
For example, that approach mitigates the chances of programmer making mistakes inside lambda function: passing the wrong argument, inverting arguments order, adding collateral effects, etc.
Then he introduces Functional interfaces, an interface that contains only an abstract method, implementing its own interface runTest with an abstract method factorial():
private static <T> void runTest(Function<T,T> factorial, T n) {
System.out.println(n+ " factorial = " + factorial.apply(n));
}
private static class ParallelStreamFactorial{
static BigInteger factorial(BigInteger n) {
return LongStream
.rangeClosed(1, n.longValue())
.parallel()
.mapToObj(BigInteger::valueOf)
.reduce(BigInteger.ONE, BigInteger::multiply);
}
}
Calling it with the following syntax:
import java.math.BigInteger;
import java.util.function.Function;
import java.util.stream.LongStream;
public static void main(String[] args) {
BigInteger n = BigInteger.valueOf(3);
runTest(ParallelStreamFactorial::factorial, n);
}
The code works and prints
3 factorial = 6
As I'm studying lambdas, I tried to interchange method reference syntax for lambda syntax, and managed to using:
public static void main(String[] args) {
BigInteger n = BigInteger.valueOf(3);
runTest((number)->ParallelStreamFactorial.factorial(number), n);
}
Which also worked.
Then he proceeds to explain built-in interfaces, such as Predicate<T>{boolean test(T t);}, and that's where I got stuck.
I managed to implement a Predicate<Integer> that tests if the integer is bigger than 0 using the three syntaxes:
Instantiating an object myPredicate from a class that implements Predicate<Integer>
Instantiating an object lambdaPredicate from a lambda
Instantiating an object methodReferencePredicatefrom a method reference:
import java.util.function.Function;
import java.util.function.Predicate;
public class MyPredicates {
public static void main(String[] args) {
Predicate<Integer> constructorPredicate = new myPredicate();
System.out.println(constructorPredicate.test(4));
Predicate<Integer> lambdaPredicate = (number)-> number > 0;
System.out.println(lambdaPredicate.test(4));
Predicate<Integer> methodReferencePredicate = myMethodReference::myTest;
System.out.println(methodReferencePredicate.test(4));
}
private static class myPredicate implements Predicate<Integer>{
public boolean test(Integer t) {
return t>0;
}
}
private static class myMethodReference{
public static boolean myTest(Integer t) {
return t>0;
}
}
}
And then calling their .test() methods. They're all three working and printing true.
However I would like to "instantiate and call" everything in a single line, as he did in his example. It seems like his code is inferring the type of the argument passed (I may be wrong) but it's definitely running automatically.
I tried different things:
Predicate<Integer>(myMethodReference::myTest, 4);
Predicate(myMethodReference::myTest, 4);
Predicate<Integer>((number) -> myMethodReference.myTest(number), 4);
Predicate((number) -> myMethodReference.myTest(number), 4);
But none of them work.
They throw:
Syntax error, insert ";" to complete LocalVariableDeclarationStatement
and
The method Predicate(myMethodReference::myTest, int) is undefined for the type MyPredicates
Errors. I also don't even know the name of what he's doing in that single line to properly search better on internet for references.
What's the correct syntax for that, whether by method reference or lambdas?
You've made things far too complicated.
There is no point in lambdas if you want to 'execute them immediately'.
Here is how you run your my test code 'immediately':
System.out.println(number > 4);
Why mess with lambdas? They just make matters confusing here.
The very point of a lambda is two-fold:
A way to transmit code itself to other contexts.
Control flow abstraction.
In java in particular, option 2 is an evil - it makes code ugly, harder to reason about, introduces pointless distractions, and in general should be avoided... unless you're employing it to avoid an even greater evil. That happens plenty - for example, a reasonable 'stream chain' is generally better even though its control flow abstraction. I'd say this:
int total = list.stream()
.filter(x -> x.length() < 5)
.mapToInt(Integer::valueOf)
.sum();
is the lesser evil compared to:
int total = 0;
for (var x : list) {
if (x.length() < 5) continue;
total += Integer.parseInt(x);
}
but it is a pretty close call.
Why is it 'evil'? Because lambdas in java are non transparent in 3 important ways, and this non-transparency is a good thing in the first case, but a bad thing in the second. Specifically, lambdas are not transparent in these ways:
Lambdas cannot change or even read local variables from outer scope unless they are (effectively) final.
Lambdas cannot throw checked exceptions even if the outer scope would handle them (because they catch them or the method you're in declared throws ThatException).
Lambdas cannot do control flow. You can't break, continue, or return from within a lambda to outside of it.
These 3 things are all useful and important things to be doing when you're dealing with basic control flow. Therefore, lambdas should be avoided as you create a bunch of problems and inflexibility by using them... unless you've avoided more complexity and inflexibility of course. It's programming: Nothing is ever easy.
The notion of bundling up code is therefore much more useful, because those non-transparencies turn into upside:
If you take the lambda code and export it to someplace that runs that code much later and in another thread, what does it even mean to modify a local variable at that point? The local variable is long gone (local vars are ordinarily declared on stack and disappear when the method that made them ends. That method has ended; your lambda survived this, and is now running in another context). Do we now start marking local vars as volatile to avoid thead issues? Oof.
The fact that the outer code deals with a checked exception is irrelevant: The lexical scope that was available when you declared the lambda is no longer there, we've long ago moved past it.
Control flow - breaking out of or restarting a loop, or returning from a method. What loop? What method? They have already ended. The code makes no sense.
See? Lambda lack of transparency is in all ways great (because they make no sense), if your lambda is 'travelling'. Hence, lambdas are best used for this, they have no downsides at that point.
Thus, let's talk about travelling lambdas: The very notion is to take code and not execute it. Instead, you hand it off to other code that does whatever it wants. It may run it 2 days from now when someone connects to your web server, using path /foobar. It may run every time someone adds a new entry to a TreeSet in order to figure out where in the tree the item should be placed (that's precisely the fate of the lambda you pass to new TreeSet<X>((a, b) -> compare-a-and-b-here).
Even in control flow situations (which are to be avoided if possible), your lambda still travels, it just travels to place that does immediately ends up using it, but the point of the lambda remains control flow abstraction: You don't run the code in it, you hand your lambda off to something else which will then immediately run that 0 to many times. That's exactly what is happening here:
list.forEach(System.out::println);
I'm taking the code notion of System.out.println(someString), and I don't run it - no, I bundle up that idea in a lambda and then pass this notion to list's forEach method which will then invoke it for me, on every item in the list. As mentioned, this is bad code, because it needlessly uses lambdas in control flow abstraction mdoe which is inferior to just for (var item : list) System.out.println(item);, but it gets the point across.
It just doesn't make sense to want to write a lambda and immediately execute it. Why not just... execute it?
In your example from the book, you don't actually execute the lambda as you make it. You just.. make it, and hand it off to the runTest method, and it runs it. The clue is, runTest is a method (vs your attempts - Predicate is not a method), it's not magical or weird, just.. a method, that so happens to take a Function<A, B> as argument, and the lambda you write so happens to 'fit' - it can be interpreted as an implementation of Function<A, B>, and thus that code compiles and does what it does.
You'd have to do the same thing.
But, if that code is a single-use helper method, then there's no point to the lambda in the first place.
Sometimes I face I must write a piece of code like this (usually it have more nested if and more complex structure but for the example is enought)
public void printIt(Object1 a){
if (a!=null){
SubObject b= a.getB();
if (b!=null){
SubObject2 c=b.getC();
if(c!=null){
c.print();
}
}
}
}
when I dont need to know what failed and if something is null do nothing, an approach could be
public void printIt(Object1 a){
try{
a.getB().getC().print();
}catch (NullPointerException e) {
}
}
Is there something wrong in this second form like performance or other kind of issues?
The exception version (similar to chains using Groovy's safe-navigation operator ?.) makes it really easy to take the Law of Demeter (or as I call it, Demeter's Strongly-Worded Suggestion) and make it your plaything for the night.
Similarly, deeply-nested if-statements leads to difficult-to-read code, and underneath it all, the same "violation" exists, and the cyclomatic complexity of such methods is high.
public void printIt(Object1 a) {
if (null == a) {
return;
}
SubObject b = a.getB();
if (null == b) {
return;
}
SubObject2 c = b.getC();
if (null == c) {
return;
}
c.print();
}
I'd rather see LAMs (Little Auxiliary Methods) in appropriate places that encapsulate the checks and pretty much eliminate the need for the question altogether.
Yes. The second version will have terrible performance.
Don't use exceptions for normal control flow. Effective Java item 57: use exceptions only for exceptional situations.
==UPDATE==
Even ignoring performance issues (exceptions are faster than they once were, according to my benchmark, but not nearly as fast as a simple if check), it's really code-smelly to use exceptions for standard program flow like this. JVM bytecode has special optimizations it can do for null checks, even in if statements. The first code sample is vastly preferred.
public void printIt(Object1 a){
if(a==null){
throw new IllegalArgumentException("a was null, but this is not allowed here."),
}
[...]
Fail fast and fail hard. If a shoud not be null, throw an Exception. This will make your code more stable and reliable.
So if I would have to decide between your a) and your b), I would choose a). But if a mustn't be null there, you would hide an error-situation.
The wrongest part of the second version is that when a NPE happens inside the getB(), getC() it will be silently ignored. As already mentioned, exceptions are for exceptional cases.
Using exceptions is always a bad idea in terms of performance, no matter how slow the mechanism used to be and is now. Whenever an exception is thrown, the full stack will be unrolled to create the stack trace. Thus, like Lois Wasserman said, you should not rely on them for (regular) program flow but for exceptional cases.
The nested ifs aren't the definition of beauty, but will give you the ability to print additional information like 'B is null' etc.
The answer is use version A.
It is generally considered "bad design" to use Exceptions for flow control. Exceptions are for the "exceptional", especially NPEs which are totally avoidable using null checks. Further, using null checks, you can tell (ie log) which term is null (you won't know where the null is with your version B).
Note that performance is not an issue any more throwing exceptions (the stack trace for example is only built if you use it). It's a matter of clean code.
However, there are some case where using exceptions for flow control is unavoidable, for example the exceptions thrown from SimpleDateFormat.parse(), because there isn't a reasonable way to tell before making the call that your input is not parsable.
Definitely (a) but you should restructure the method to avoid nesting the if statements as mentioned in a previous answer. Exceptions are not the performance hit they once were but are still much slower than checking for null and should never be used for program flow control like this. If an object can be null you should check for it but if it is not allowed you should fail fast at the point you assign the object reference. In many circumstances you can have default implementations (empty list is a good example) to avoid nulls altogether which results in much cleaner code. Avoid nulls whenever you can.
Using Java 8 optional:
Optional.ofNullable(a)
.map(Object1::getB)
.map(SubObject::getC)
.ifPresent(Object2::print);
If you migrate to Java 8 you can use Optional and Lambdas. First, you need to rewrite your classes to return Optional of each type:
class Object1 {
private SubObject b;
Optional<SubObject> getB() {
return Optional.ofNullable(b);
}
}
class SubObject {
private SubObject2 c;
Optional<SubObject2> getC() {
return Optional.ofNullable(c);
}
}
class SubObject2 {
#Override
public String toString() {
return "to be printed";
}
}
Now, you can chain the calls without the risk of NullPointerExceptions in a concise way:
a.getB()
.flatMap(SubObject::getC)
.ifPresent(System.out::println);
See the Oracle's article Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional! for more information.
A code should never include exception handlers for unchecked exceptions. A null check should always be used for an object reference which has a chance of being null.
I'm surprised at how it is possible to continue execution even after a StackOverflowError has occurred in Java.
I know that StackOverflowError is a sublass of the class Error.
The class Error is decumented as "a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch."
This sounds more like a recommendation than a rule, subtending that catching a Error like a StackOverflowError is in fact permitted and it's up to the programmer's reasonability not to do so. And see, I tested this code and it terminates normally.
public class Test
{
public static void main(String[] args)
{
try {
foo();
} catch (StackOverflowError e) {
bar();
}
System.out.println("normal termination");
}
private static void foo() {
System.out.println("foo");
foo();
}
private static void bar() {
System.out.println("bar");
}
}
How can this be? I think by the time the StackOverflowError is thrown, the stack should be so full that there is no room for calling another function. Is the error handling block running in a different stack, or what is going on here?
When the stack overflows and StackOverflowError is thrown, the usual exception handling unwinds the stack. Unwinding the stack means:
abort the execution of the currently active function
delete its stack frame, proceed with the calling function
abort the execution of the caller
delete its stack frame, proceed with the calling function
and so on...
... until the exception is caught. This is normal (in fact, necessary) and independent of which exception is thrown and why. Since you catch the exception outside of the first call to foo(), the thousands of foo stack frames that filled the stack have all been unwound and most of the stack is free to be used again.
When the StackOverflowError is thrown, the stack is full. However, when it's caught, all those foo calls have been popped from the stack. bar can run normally because the stack is no longer overflowing with foos. (Note that I don't think the JLS guarantees you can recover from a stack overflow like this.)
When the StackOverFlow occurs, the JVM will pop down to the catch, freeing the stack.
In you example, it get rids of all the stacked foo.
Because the stack doesn't actually overflow. A better name might be AttemptToOverflowStack. Basically what it means is that the last attempt to adjust the stack frame errs because there isn't enough free space left on the stack. The stack could actually have lots of space left, just not enough space. So, whatever operation would have depended upon the call succeeding (typically a method invocation), never gets exectued and all that is left is for the program to deal with that fact. Which means that it is really no different from any other exception. In fact, you could catch the exception in the function that is making the call.
As has already been answered, it is possible to execute code, and in particular to call functions, after catching a StackOverflowError because the normal exception handling procedure of the JVM unwinds the stack between the throw and the catch points, freeing stack-space for you to use. And your experiment confirms that is the case.
However, that is not quite the same as saying that it is, in general, possible to recover from a StackOverflowError.
A StackOverflowError IS-A VirtualMachineError, which IS-AN Error. As you point out, Java provides some vague advice for an Error:
indicates serious problems that a reasonable application should not try to catch
and you, reasonably, conclude that should sounds like catching an Error might be OK in some circumstances. Note that performing one experiment does not demonstrate that something is, in general, safe to do. Only the rules of the Java language and the specifications of the classes you use can do that. A VirtualMachineError is a special class of exception, because the Java Language Specification and the Java Virtual Machine Specification provide information about the semantics of this exception. In particular, the latter says:
A Java Virtual Machine implementation throws an object that is an instance of a subclass of the class VirtualMethodError when an internal error or resource limitation prevents it from implementing the semantics described in this chapter. 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 VirtualMethodError subclasses defined below may be thrown at any time during the operation of the Java Virtual Machine:
...
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.
The crucial problem is that you "cannot predict" where or when a StackOverflowError will be thrown. There are no guarantees about where it will not be thrown. You can not rely on it being thrown on entry to a method, for example. It could be thrown at a point within a method.
This unpredictability is potentially disastrous. As it can be thrown within a method, it could be thrown part way through a sequence of operations that the class considers to be one "atomic" operation, leaving the object in a partially modified, inconsistent, state. With the object in an inconsistent state, any attempt to use that object could result in erroneous behaviour. In all practical cases you can not know which object is in an inconsistent state, so you have to assume that no objects are trustworthy. Any recovery operation or attempt to continue after the exception is caught could therefore have erroneous behaviour. The only safe thing to do is therefore to not catch a StackOverflowError, but rather to allow the program to terminate. (In practice you might attempt to do some error logging to assist troubleshooting, but you can not rely on that logging operating correctly). That is, you can not reliably recover from a StackOverflowError.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
How can I handle StackOverflowError in Java?
I'm not sure what you mean with "handle".
You can certainly catch that error:
public class Example {
public static void endless() {
endless();
}
public static void main(String args[]) {
try {
endless();
} catch(StackOverflowError t) {
// more general: catch(Error t)
// anything: catch(Throwable t)
System.out.println("Caught "+t);
t.printStackTrace();
}
System.out.println("After the error...");
}
}
but that is most likely a bad idea, unless you know exactly what you are doing.
You probably have some infinite recursion going on.
I.e. a method that calls itself over and over
public void sillyMethod()
{
sillyMethod();
}
One to handle this is to fix your code so that the recursion terminates instead of continuing forever.
Take a look at Raymond Chen's post When debugging a stack overflow, you want to focus on the repeating recursive part. An extract:
If you go hunting through your defect tracking database trying to see whether this is a known issue or not, a search for the top functions on the stack is unlikely to find anything interesting. That's because stack overflows tend to happen at a random point in the recursion; each stack overflow looks superficially different from every other one even if they are the same stack overflow.
Suppose you're singing the song Frère Jacques, except that you sing each verse a few tones higher than the previous one. Eventually, you will reach the top of your singing range, and precisely where that happens depends on where your vocal limit lines up against the melody. In the melody, the first three notes are each a new "record high" (i.e., the notes are higher than any other note sung so far), and new record highs appear in the three notes of the third measure, and a final record high in the second note of the fifth measure.
If the melody represented a program's stack usage, a stack overflow could possibly occur at any of those five locations in the program's execution. In other words, the same underlying runaway recursion (musically represented by an ever-higher rendition of the melody) can manifest itself in five different ways. The "recursion" in this analogy was rather quick, just eight bars before the loop repeated. In real life, the loop can be quite long, leading to dozens of potential points where the stack overflow can manifest itself.
If you are faced with a stack overflow, then, you want to ignore the top of the stack, since that's just focusing on the specific note that exceeded your vocal range. You really want to find the entire melody, since that's what's common to all the stack overflows with the same root cause.
You might want to see if the "-Xss" option is supported by your JVM. If so, you might want to try setting it to a value of 512k (default is 256k under 32-bit Windows and Unix) and see if that does anything (other than make you sit longer until your StackOverflowException). Note that this is a per-thread setting, so if you've got a lot of threads running you also might want to bump up your heap settings.
The correct answer is the one already given. You likely either a) have a bug in your code leading to an infinite recursion which is usually quite easy to diagnose and fix, or b) have code which can lead to very deep recursions for example recursively traversing an unbalanced binary tree. In the latter situation, you need to alter your code to not allocate the information on the stack (i.e. to not recurse) but to instead allocate it in the heap.
For example, for an unbalanced tree traversal, you could store the nodes that will need to be revisited in a Stack data structure. For an in order traversal you would loop down the left branches pushing each node as you visited it until you hit a leaf, which you would process, then pop a node off the top of the stack, process it, then restart your loop with the right child (by just setting your loop variable to the right node.) This will use a constant amount of stack by moving everything that was on the stack to the heap in the Stack data structure. Heap is typically much more plentiful than stack.
As something that is usually an extremely bad idea, but is necessary in cases where memory use is extremely constrained, you can use pointer reversal. In this technique, you encode the stack into the structure you are traversing, and by reusing the links you are traversing, you can do this with no or significantly less additional memory. Using the above example, instead of pushing nodes when we loop, we just need to remember our immediate parent, and at each iteration, we set the link we traversed to the current parent and then the current parent to the node we are leaving. When we get to a leaf, we process it, then go to our parent and then we have a conundrum. We don't know whether to correct the left branch, process this node, and continue with the right branch, or to correct the right branch and go to our parent. So we need to allocate an extra bit of information as we iterate. Typically, for low-level realizations of this technique, that bit will be stored in the pointer itself leading to no additional memory and constant memory overall. This is not an option in Java, but it may be possible to squirrel away this bit in fields used for other things. In the worst-case, this is still at least 32 or 64 times reduction in the amount of memory needed. Of course, this algorithm is extremely easy to get wrong with completely confusing results and would raise utter havoc with concurrency. So it's almost never worth the maintenance nightmare except where allocating memory is untenable. The typical example being a garbage collector where algorithms like this are common.
What I really wanted to talk about, though, is when you might want to handle the StackOverflowError. Namely to provide tail call elimination on the JVM. One approach is to use trampoline style where instead of performing a tail call you return a nullary procedure object, or if you are just returning a value you return that. [Note: this requires some means of saying a function returns either A or B. In Java, probably the lightest way to do this is to return one type normally and throw the other as an exception.] Then whenever you call a method, you need to do a while loop calling the nullary procedures (which will themselves return either a nullary procedure or a value) until you get a value. An endless loop will become a while loop that is constantly forcing procedure objects that return procedure objects. The benefits of trampoline style is that it only uses a constant factor more stack than you would use with an implementation that properly eliminated all tail calls, it uses the normal Java stack for non-tail calls, the translation simple, and it only grows the code by a (tedious) constant factor. The drawback is you allocate an object on every method call (which will immediately become garbage) and consuming these objects involves a couple of indirect calls per tail call.
The ideal thing to do would be to never allocate those nullary procedures or anything else in the first place, which is exactly what tail call elimination would accomplish. Working with what Java provides though, what we could do is run the code as normal and only make these nullary procedures when we run out of stack. Now we still allocate those useless frames, but we do so on the stack rather than the heap and deallocate them in bulk, also, our calls are normal direct Java calls. The easiest way to describe this transformation is to first rewrite all multi-call-statement methods into methods that have two call statements, i.e. fgh() { f(); g(); h(); } becomes fgh() { f(); gh(); } and gh(){ g(); h(); }. For simplicity, I'll assume all methods end in a tail call, which can be arranged by just packaging the remainder of a method into a separate method, though in practice, you'd want to handle these directly. After these transformations we have three cases, either a method has zero calls in which case there is nothing to do, or it has one (tail) call, in which case we wrap it in a try-catch block in the same we will for the tail call in the two call case. Finally, it may have two calls, a non-tail call and a tail call, in which case we apply the following transformation illustrated by example (using C#'s lambda notation which could easily be replaced with an anonymous inner class with some growth):
// top-level handler
Action tlh(Action act) {
return () => {
while(true) {
try { act(); break; } catch(Bounce e) { tlh(() => e.run())(); }
}
}
}
gh() {
try { g(); } catch(Bounce e) {
throw new Bounce(tlh(() => {
e.run();
try { h(); } catch(StackOverflowError e) {
throw new Bounce(tlh(() => h());
}
});
}
try { h(); } catch(StackOverflowError e) {
throw new Bounce(tlh(() => h()));
}
}
The main benefit here is if no exception is thrown, this is the same code as we started with just with some extra exception handlers installed. Since tail calls (the h() call) don't handle the Bounce exception, that exception will fly through them unwinding those (unnecessary) frames from the stack. The non-tail calls catch the Bounce exceptions and rethrow them with the remaining code added. This will unwind the stack all the way up to the top level, eliminating the tail call frames but remembering the non-tail call frames in the nullary procedure. When we finally execute the procedure in the Bounce exception at the top-level, we will recreate all the non-tail call frames. At this point, if we immediately run out of stack again, then, since we don't reinstall the StackOverflowError handlers, it will go uncaught as desired, since we really are out of stack. If we get a little further, a new StackOverflowError will be installed as appropriate. Furthermore, if we do make progress, but then do run out of stack again, there is no benefit re-unwinding the frames we already unwound, so we install new top-level handlers so that the stack will only be unwound up to them.
The biggest problem with this approach is that you'll probably want to call normal Java methods and you may have arbitrarily little stack space when you do, so they may have enough space to start but not finish and you can't resume them in the middle. There are at least two solutions to this. The first is to ship all such work to a separate thread which will have it's own stack. This is pretty effective and pretty easy and won't introduce any concurrency (unless you want it to.) Another option is simply to purposely unwind the stack before calling any normal Java method by simply throwing a StackOverflowError immediately before them. If it still runs out of stack space when you resume, then you were screwed to begin with.
A similar thing can be done to make continuations just-in-time too. Unfortunately, this transformation isn't really bearable to do by hand in Java, and is probably borderline for languages like C# or Scala. So, transformations like this tend to be done by languages that target the JVM and not by people.
I guess you can't - or it at least depends on the jvm you use. Stack overflow means, that you have no room to store local variables and return adresses. If your jvm does some form of compiling, you have the stackoverflow in the jvm as well and that means, you can't handle it or catch it. The jvm has to terminate.
There could be a way to create a jvm that allows for such behavior, but it would be slow.
I have not tested the behavior with the jvm, but in .net you just can't handle the stackoverflow. Even try catch won't help. Since java and .net rely on the same concept (virtual machines with jit) I suspect java would behave the same. The presence of a stackoverflow-exception in .NET suggests, there might be some vm that does enable the program to catch it, the normal does not though.
Most chances to get StackOverflowError are by using [long/infinite] recursions in a recursive functions.
You can avoid Function recursion by changing your application design to use stackable data objects. There are coding patterns to convert recursive codes to iterative code blocks. Have a look at below answeres:
way-to-go-from-recursion-to-iteration
can-every-recursion-be-converted-into-iteration
design-patterns-for-converting-recursive-algorithms-to-iterative-ones
So, you avoid memory stacking by Java for your recessive function calls, by using your own data stacks.
On some occasions, you can't catch StackOverflowError.
Whenever you try, you will encounter a new one. Because it is the Java VM. It's good to find recursive code blocks, like Andrew Bullock's said.
The stack trace should indicate the nature of the problem. There should be some obvious looping when you read the stack trace.
If it's not a bug, you need add a counter or some other mechanism to halt the recursion before the recursion goes so deep it causes a stack overflow.
An example of this might be if you're handling nested XML in a DOM model with recursive calls and the XML is nested so deep it causes a stack overflow with your nested calls (unlikely, but possible). This would have to be pretty deep nesting to cause a stack overflow though.
As mentioned by many in this thread, the common cause for this is a recursive method call that doesn't terminate. Where possible avoid the stack overflow and if you this in testing you should consider this in most cases to be a serious bug. In some cases you can configure the thread stack size in Java to be larger to handle some circumstances ( large data sets being managed in local stack storage, long recursive calls) but this will increase the overall memory footprint which can lead to issues in the number of threads available in the VM. Generally if you get this exception the thread and any local data to this thread should be considered toast and not used( ie suspect and possibly corrupt).
Simple,
Look at the stack trace that the StackOverflowError produces so you know where in your code it occurs and use it to figure out how to rewrite your code so that it doesn't call itself recursively (the likely cause of your error) so it won't happen again.
StackOverflowErrors are not something that needs to be handled via a try...catch clause but it points to a basic flaw in the logic of your code that needs to be fixed by you.
java.lang.Error javadoc:
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.
So, don't. Try to find what's wrong in the logic of your code. This exception ocurrs very often because of infinite recursion.
StackOverFlow error - when you create a method in Java at the time some size of memory will be allocated in the stack memory. If you create a method inside the infinite loop then a memory allocation will be created 'n' times. When the limit for memory allocation is exceeded then the error will occur. The error is called a StackOverFlow error.
If you want to avoid this error please consider the stack memory size during the implementation from the beginning.
/*
Using Throwable we can trap any know error in JAVA..
*/
public class TestRecur {
private int i = 0;
public static void main(String[] args) {
try {
new TestRecur().show();
} catch (Throwable err) {
System.err.println("Error...");
}
}
private void show() {
System.out.println("I = " + i++);
show();
}
}
However you may have a look at the link: http://marxsoftware.blogspot.in/2009/07/diagnosing-and-resolving.html to understand the code snippet, which may raise error
I am being powerfully tempted to use an unchecked exception as a short-circuit control-flow construct in a Java program. I hope somebody here can advise me on a better, cleaner way to handle this problem.
The idea is that I want to cut short the recursive exploration of sub-trees by a visitor without having to check a "stop" flag in every method call. Specifically, I'm building a control-flow graph using a visitor over the abstract syntax tree. A return statement in the AST should stop exploration of the sub-tree and send the visitor back to the nearest enclosing if/then or loop block.
The Visitor superclass (from the XTC library) defines
Object dispatch(Node n)
which calls back via reflection methods of the form
Object visitNodeSubtype(Node n)
dispatch is not declared to throw any exceptions, so I declared a private class that extends RuntimeException
private static class ReturnException extends RuntimeException {
}
Now, the visitor method for a return statement looks like
Object visitReturnStatement(Node n) {
// handle return value assignment...
// add flow edge to exit node...
throw new ReturnException();
}
and every compound statement needs to handle the ReturnException
Object visitIfElseStatement(Node n) {
Node test = n.getChild(0);
Node ifPart = n.getChild(1);
Node elsePart = n.getChild(2);
// add flow edges to if/else...
try{ dispatch(ifPart); } catch( ReturnException e ) { }
try{ dispatch(elsePart); } catch( ReturnException e ) { }
}
This all works fine, except:
I may forget to catch a ReturnException somewhere and the compiler won't warn me.
I feel dirty.
Is there a better way to do this? Is there a Java pattern I am unaware of to implement this kind of non-local flow-of-control?
[UPDATE] This specific example turns out to be somewhat invalid: the Visitor superclass catches and wraps exceptions (even RuntimeExceptions), so the exception throwing doesn't really help. I've implemented the suggestion to return an enum type from visitReturnStatement. Luckily, this only needs to be checked in a small number of places (e.g., visitCompoundStatement), so it's actually a bit less hassle than throwing exceptions.
In general, I think this is still a valid question. Though perhaps, if you are not tied to a third-party library, the entire problem can be avoided with sensible design.
I think this is a reasonable approach for a few reasons:
You are using a 3rd party and are unable to add the checked exception
Checking return values everywhere in a large set of visitors when it's only necessary in a few is an unnecessary burden
Also, there are those that have argued that unchecked exceptions aren't all that bad. Your usage reminds me of Eclipse's OperationCanceledException which is used to blow out of long-running background tasks.
It's not perfect, but, if well documented, it seems ok to me.
Throwing a runtime exception as control logic is definitely a bad idea. The reason you feel dirty is that you're bypassing the type system, i.e. the return type of your methods is a lie.
You have several options that are considerably more clean.
1. The Exceptions Functor
A good technique to use, when you're restricted in the exceptions you may throw, if you can't throw a checked exception, return an object that will throw a checked exception. java.util.concurrent.Callable is an instance of this functor, for example.
See here for a detailed explanation of this technique.
For example, instead of this:
public Something visit(Node n) {
if (n.someting())
return new Something();
else
throw new Error("Remember to catch me!");
}
Do this:
public Callable<Something> visit(final Node n) {
return new Callable<Something>() {
public Something call() throws Exception {
if (n.something())
return new Something();
else
throw new Exception("Unforgettable!");
}
};
}
2. Disjoint Union (a.k.a. The Either Bifunctor)
This technique lets you return one of two different types from the same method. It's a little bit like the Tuple<A, B> technique that most people are familiar with for returning more than one value from a method. However, instead of returning values of both types A and B, this involves returning a single value of either type A or B.
For example, given an enumeration Fail, which could enumerate applicable error codes, the example becomes...
public Either<Fail, Something> visit(final Node n) {
if (n.something())
return Either.<Fail, Something>right(new Something());
else
return Either.<Fail, Something>left(Fail.DONE);
}
Making the call is now much cleaner because you don't need try/catch:
Either<Fail, Something> x = node.dispatch(visitor);
for (Something s : x.rightProjection()) {
// Do something with Something
}
for (Fail f : x.leftProjection()) {
// Handle failure
}
The Either class is not very difficult to write, but a full-featured implementation is provided by the Functional Java library.
3. The Option Monad
A little bit like a type-safe null, this is a good technique to use when you do not want to return a value for some inputs, but you don't need exceptions or error codes. Commonly, people will return what's called a "sentinel value", but Option is considerably cleaner.
You now have...
public Option<Something> visit(final Node n) {
if (n.something())
return Option.some(new Something());
else
return Option.<Something>none();
}
The call is nice and clean:
Option<Something> s = node.dispatch(visitor));
if (s.isSome()) {
Something x = s.some();
// Do something with x.
}
else {
// Handle None.
}
And the fact that it's a monad lets you chain calls without handling the special None value:
public Option<Something> visit(final Node n) {
return dispatch(getIfPart(n).orElse(dispatch(getElsePart(n)));
}
The Option class is even easier to write than Either, but again, a full-featured implementation is provided by the Functional Java library.
See here for a detailed discussion of Option and Either.
Is there a reason you aren't just returning a value? Such as NULL, if you really want to return nothing? That would be a lot simpler, and wouldn't risk throwing an unchecked runtime exception.
I see the following options for you:
Go ahead and define that RuntimeException subclass. Check for serious problems by catching your exception in the most general call to dispatch and reporting that one if it gets that far.
Have the node processing code return a special object if it thinks searching should end abruptly. This still forces you to check return values instead of catching exceptions, but you might like the look of the code better that way.
If the tree walk is to be stopped by some external factor, do it all inside a subthread, and set a synchronized field in that object in order to tell the thread to stop prematurely.
Why are you returning a value from your visitor? The appropriate method of the visitor is called by classes that are being visited. All work done is encapsulated within the visitor class itself, it should return nothing and handle it's own errors. The only obligation required of the calling class is to call the appropriate visitXXX method, nothing more. (This assumes you are using overloaded methods as in your example as opposed to overriding the same visit() method for each type).
The visited class should not be changed by the visitor or have to have any knowledge of what it does, other than it allows the visit to happen. Returning a value or throwing an exception would violate this.
Visitor Pattern
Do you have to use Visitor from XTC? It's a pretty trivial interface, and you could implement your own which can throw checked ReturnException, which you would not forget to catch where needed.
I've not used the XTC library you mention. How does it supply the complementary part of the visitor pattern - the accept(visitor) method on nodes? Even if this is a reflection based dispatcher, there must still be something that handles recursion down the syntax tree?
If this structural iteration code is readily accessible, and you're not already using the return value from your visitXxx(node) methods, could you exploit a simple enumerated return value, or even a boolean flag, telling accept(visitor) not to recurse into child nodes?
If:
accept(visitor) isn't explicitly implemented by nodes (there's some field or accessor reflection going on, or nodes just implement a child-getting interface for some standard control-flow logic, or for any other reason...), and
you don't want to mess with the structural iterating part of the library, or it's not available, or it's not worth the effort...
then as a last resort I guess that exceptions might be your only option whilst still using the vanilla XTC library.
An interesting problem though, and I can understand why exception-based control flow makes you feel dirty...