5

I was just trying something with try-catch and this code:

public class MainThread
{
    public static void main(String [] args) 
    {
        try 
        {
            badMethod();  
            System.out.print("A"); 
        }  
        catch (Exception ex) 
        {
            System.out.print("B");  
        } 
        finally 
        {
            System.out.print("C"); 
        } 
        System.out.print("D"); 
    }  
    public static void badMethod() 
    {
        throw new Error(); /* Line 22 */
    } 
}

I understand Error will not be caught by the catch block above, but the finally block will be executed, and then the JVM will terminate.

But when I try to run the program many times, I get different outputs:

C printed before the stack trace:

CException in thread "main" java.lang.Error
  at MainThread.badMethod(MainThread.java:22)
  at MainThread.main(MainThread.java:7)

or C printed after the stack trace:

Exception in thread "main" java.lang.Error
  at MainThread.badMethod(MainThread.java:22)
  at MainThread.main(MainThread.java:7)
C

Can anyone explain this behavior?

codingenious
  • 8,385
  • 12
  • 60
  • 90

2 Answers2

11

The System.out stream and the System.err stream are separate streams which both have the same output. As such there is a race between them and which "wins" cannot be determined in advance.

As Luiggi Mendoza says;

In order to get the desired result, OP just have to change System.out.print to System.error.print or catch the Error and print it using e.printStacktrace(System.out). Or even better, use a logger that handles all this work for you

It is additionally worth noting that your catch statement does not catch this new Error() because Error!=Exception

Richard Tingle
  • 16,906
  • 5
  • 52
  • 77
1

Change

    catch (Exception ex) 

into

    catch (Throwable ex) 

which catches more (Throwable being the base class). It also catches the stack trace in badMethod, which probably does e.printStacktrace(), which calls e.printStacktrace(System.err). Exception is for checked Exception, not RuntimeExceptions.

To the console both writers (PrintStreams), System.out and System.err are written simultaneous, in different threads: so really mixed up.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • I know Throwable can be used, but @Richard answered what I was looking for. Although your answer also provides good info. +1:) – codingenious Oct 28 '13 at 14:43
  • Thanks, he was first. I just wanted to point out about Throwable; in some verbosity as the question+answer might be sought in the future by others. – Joop Eggen Oct 28 '13 at 14:45
  • 1
    Part about different threads is wrong, though; separate buffers, same thread. – Ernest Friedman-Hill Oct 28 '13 at 14:55
  • @ErnestFriedman-Hill so repeated runs should cause the same garbled console under the same condition? Thanks. – Joop Eggen Oct 28 '13 at 15:34
  • 1
    The indeterminate behavior comes from the OS; if the Java program doesn't flush the buffers, it's up to the OS as to when the data is pulled from each of the buffers and displayed. – Ernest Friedman-Hill Oct 28 '13 at 15:44