0

Here says that it is impossible to recover from errors. I am not sure what does it mean because I can catch Error just like Exception. Eg:

public static void main(String args[]) {
    while (true) {
        try {
            throw new StackOverflowError("stackoverflow");
        } catch (Throwable throwable) {
            //do something
        }
        //program recover and continue to execute
    }
}

The above program execute normally and It seems that It's possible to recover from errors. Can anyone help?

UPDATE:

example of stackoverflow is a little puzzling, only idiot want to recover from stackoverflow. Here is another example about OutOfMemory:

public class Main {
    public static Map<Long, Object> cache = null;
    public static void main(String args[]){
        while(true){
            try {
                if(cache == null) {
                    cache = new HashMap<>();
                }
                for (long i = 0; i < Long.MAX_VALUE; ++i) {
                    cache.put(i, i);
                }
            }catch(OutOfMemoryError error) {
                cache.clear();//delete some unused entry or clear all.
                cache = null;
                System.gc();
                System.out.println("release memory");
            }
        }
    }
} 

It's a simple HashMap cache, execute the code using java -Xmx1m Main , and we will see an OutOfMemoryError soon, then release memory manually, and the program will continue to execute. insert-> OutOfMemoryError -> release -> insert... See? the program have recovered from an OutOfMemoryError. Isn't it? And I think it's meaningful. So, Why someone still said program can't recover from OutOfMemoryError.

expoter
  • 1,466
  • 12
  • 29
  • 1
    How would you recover from an actual StackOverflowError? – Michael Markidis Jul 15 '16 at 03:18
  • @Michale Markidis, Just catch StackOverflowError and continue execution, I guess. I am not sure about the meaning of "recover from an error". – expoter Jul 15 '16 at 03:21
  • Consider an [`OutOfMemoryError`](https://docs.oracle.com/javase/7/docs/api/java/lang/OutOfMemoryError.html), how would you attempt to continue execution? – Elliott Frisch Jul 15 '16 at 03:25
  • @ Jonny Henly, Why can't catch a StackOverflowError, see the above code snippet, StackOverflowError is obviously catched. Or do you mean that programmer should avoid to catch StackOverflowError, even the compiler has no constraint on that? – expoter Jul 15 '16 at 03:27
  • 1
    Also look at [this](http://stackoverflow.com/questions/8728866/no-throw-virtualmachineerror-guarantees), [this](http://stackoverflow.com/questions/2679330/catching-java-lang-outofmemoryerror), and [this (probably a better duplicate source)](http://stackoverflow.com/questions/352780/when-to-catch-java-lang-error) – Krease Jul 16 '16 at 07:44
  • @Krease, Thanks, they are very helpful. – expoter Jul 17 '16 at 07:28

3 Answers3

3

Obviously, the mere ability to "catch" an exception does not mean that you will (always ...) be able to "recover from" it ...

... i.e.:   "to sally forth, entirely unscathed, as though 'such an inconvenient event' never had occurred in the first place."

I think that the essential point of the original author is more-or-less that:   Even though the poor souls on the Titanic might have "caught" the fact that their ship was sinking, there was nothing that they could do to "recover" the ship and to sail it on unscathed to New York.

--- Edit: "Now, let me add one more thought!" (As other Answerers have also done here.) Sometimes, an Error Exception is intentionally "thrown" in some block of code that has intentionally been surrounded by a catch-block.

Maybe the error (which is itself "an object") is of a particular user-defined type that the catcher will recognize. (He can "re-throw" any that he does not recognize, or simply decline to catch it.) This can be a very elegant and efficient way to handle, well, "the exceptions to the rule." (Hence the name...)

Whenever a block of code encounters a situation that "only happens once in a blue moon, but it just did," it can throw an exception high into the air, knowing that the nearest catcher will catch it. This catcher, in turn, can recognize the thing that just landed into his baseball-mitt, and respond accordingly. There can be any number of "catchers" out there, looking for different things.

This strategy is not "an Error," but rather an intentional alternative flow-of-control within the program.

Mike Robinson
  • 7,537
  • 2
  • 17
  • 28
  • There was nothing that they could do to "recover"? I think I can release some memory when encounter an OutOfMemoryError rather than terminate the program immediately. See UPDATE please. – expoter Jul 15 '16 at 04:16
  • 1
    @expoter The problem is that if an `Error` occurred, the JVM might be in an inconsistent state. You could try to continue the program, but more unexpected problems might occur because the JVM state is corrupted. In other words, it's not safe to continue the program, because things might be in an unpredictable state. – Jesper Jul 15 '16 at 05:35
1

Consider the following code which actually throws a StackOverflowError

public class Code
{
    public static void main(String[] args)
    {
        try
        {
            f();
        }
        catch (Throwable t)
        {               
            System.out.println("OK I'm recovered, let me try that again");

            try
            {
                f();
            }
            catch (Throwable t2)
            {
                System.out.println("What's going on here??");

                // let me try one more time.. 
                try
                {
                   f();
                }
                catch (Throwable t3)
                {
                     System.out.println("Why can't I really recover");
                }
            }
        }

    }

    // Bad recursion...
    private static void f()
    {
        f();
    }
}

Do you really want to continue with execution knowing that your code has such an issue? What if you need to call f() again somewhere down the line? You would want to have such code in production that tries to continue if a method keeps giving a StackOverflowError?

Michael Markidis
  • 4,093
  • 1
  • 11
  • 21
  • I think the program recover from StackOverflowError, and continue to execute code in catch block, then the main method exit normally. Is it? If it can't recover from StackOverflowError, I think the program should exit immediately when it encounters StackOverflowError. – expoter Jul 15 '16 at 03:36
  • Right, but the point is: there is still a problem with the code (the StackOverflowError from the bad recursion). Do you really want to continue with execution knowing that your code has such an issue? What if you need to call f() again somewhere down the line? – Michael Markidis Jul 15 '16 at 03:39
  • Hey, Michael, StackOverflowError is a little meanless. So, I add another example about OutOfMemoryError. I think the program can recover from an OutOfMemoryError, Isn't It? See UPDATE please. – expoter Jul 15 '16 at 04:13
  • 1
    @expoter I took a look at your new example. The things is it's a very contrived example. You know why the `OutOfMemoryError` is happening so you know exactly what to do to fix it. In most real world cases, there's no way you are going to know why the `OutOfMemoryError` is happening in real-time. To illustrate that, instead of clearing the memory as your first statement in the catch block, try doing something else like a `System.out.print("got an OutOfMemoryError");` and you won't be able to. – Michael Markidis Jul 15 '16 at 05:00
0

You're just catching the Throwable here, before it ever gets to the point where it's an error. Throwable is the superclass of both errors and exceptions. Therefore, a Throwable is not comparable to an error itself, much less a StackOverflowError, and your program is not recovering from an error.

An exception is sort of like a misdemeanor charge. It's not a fantastic thing to happen to you, or rather, your program, but it definitely won't land you in jail for extended periods of time. However, an error is dangerous - it is on the level of a felony, to continue this analogy. Java is considered safer than, say, C, because it will tell you when you are doing something that is unsafe. C, on the other hand, will allow you to access data that is beyond the scope of an array, for example, and you'll get awful bugs that are very difficult to debug that way.

The analogy to crime ends after that point. If you had scrolled down a little further on the page that you linked to, it continues to delineate the reasons why exceptions and errors are different, namely, that "errors are caused by the environment in which the application is running," and therefore, because your application is only in charge of itself, and not the actual environment, it cannot of its own volition recover from an error.

The page also gives the example of an OutOfMemoryError. While you, as the programmer, can plan ahead to try to prevent an OutOfMemoryError by making your code as efficient as you can, you won't be able to prevent such an error if the code is run on a machine that has, say, 1 byte of RAM. Errors cannot be caught because they are (mostly) out of the hands of the application itself. It's up to the programmer, such as in Michael Markidis' example, to not cause an error and avoid any error-causing programming techniques (such as using "Bad recursion") that will crash your program.

Community
  • 1
  • 1
a. seo
  • 3
  • 4
  • Agreed. "Stack overflow," "out of memory," "GPF," and so-on are *clearly* "edge cases" in which you can probably only *attempt* to "land four paws down." But, if this happens to you, *"you're gonna **land**, and land hard."* You dare not attempt to keep going. There's smoke in the cockpit. Get that puppy on the tarmac, shut off the engine, get out and run away ... – Mike Robinson Jul 15 '16 at 13:22