Why did println run before printStackTace?

6

I was studying Java Handling Exceptions and this question came to me that I could not find on Google.

Why in this example did he print the first line of printStackTrace, and already gave println, and then the rest of printStackTrace?

    
asked by anonymous 10.05.2017 / 21:14

2 answers

10

At first an operating system works with 3 queues System.err (flow output for standard stderr error) , System.out (standard stdout flow output) System.in (stdin data entry)

By using PrintStackTrace , it writes by default in System.err and also reports a stack trace, that is, the chain of methods that led to the exception.

In a simple Java console application, both outputs ( System.err and System.out ) will be the same (application console) but you can reconfigure the streams for eg System.out print on console and System.err write to a file for example.

Regarding order, both run in the same sequence, but the operating system can randomly choose which queue to print first ( stderr or stdout ).

for example

public static void main(String[] args) {
    System.out.println("stdout -> 1");
    System.out.println("stdout -> 2");
    System.out.println("stdout -> 3");
    System.err.println("stderr -> 1");
    System.err.println("stderr -> 2");
    System.err.println("stderr -> 3");
}

In this code snippet I send 3 instructions to stdout and 3 to stderr, they will be executed in sequence, but each queue can take random order from the OS.

You will see that with each execution it will change the order of the queues, but the order of instructions for the queue will not, the impression for stdout will respect the sequence (1, 2, 3) and for stderr also (1 , 2, 3) but the order that it will display the queue will not respect this sequence (stdout, stderr)

There is a way to synchronize the two queues, but it is a kind of hack:

public class ConsoleHackTools {

    private static OutputStream lastStream = null;
    private static boolean isFixed = false;

    private static class FixedStream extends OutputStream {

        private final OutputStream target;

        public FixedStream(OutputStream originalStream) {
            target = originalStream;
        }

        @Override
        public void write(int b) throws IOException {
            if (lastStream != this)
                swap();
            target.write(b);
        }

        @Override
        public void write(byte[] b) throws IOException {
            if (lastStream != this)
                swap();
            target.write(b);
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            if (lastStream != this)
                swap();
            target.write(b, off, len);
        }

        private void swap() throws IOException {
            if (lastStream != null) {
                lastStream.flush();
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                }
            }
            lastStream = this;
        }

        @Override
        public void close() throws IOException {
            target.close();
        }

        @Override
        public void flush() throws IOException {
            target.flush();
        }
    }

    public static void fixConsole() {
        if (isFixed)
            return;
        isFixed = true;
        System.setErr(new PrintStream(new FixedStream(System.err)));
        System.setOut(new PrintStream(new FixedStream(System.out)));
    }
}

With this hack, changing the example of sysout and syserr earlier would look like this:

public static void main(String[] args) {
    ConsoleHackTools.fixConsole();

    System.out.println("stdout -> 1");
    System.out.println("stdout -> 2");
    System.out.println("stdout -> 3");
    System.err.println("stderr -> 1");
    System.err.println("stderr -> 2");
    System.err.println("stderr -> 3");
}

In this code, you will see that now the application will respect the sequence stdout (1, 2, 3), stderr (1, 2, 3) and also the sequence of rows (stdout, stderr)     

11.05.2017 / 14:21
3

Operating systems have two main streams of outputs: standard output or STDOUT and standard error or STDERR (accessed in java by System.out and System.err Streams). The error messages, for example the printStackTrace that you used in the code, are printed in STDERR.

When you open a terminal, by default you see both being printed simultaneously, but they are independent and so the order that they are printed may vary. You can redirect the outputs to analyze them independently. For example, in Linux, to wrap the default output for the resultado.txt file and the default error for the file erro.txt

java Metodo1 > resultado.txt 2> erro.txt

In the file resultado.txt I would have:

Acabou o Programa!

Already in the file erro.txt :

SenhaInvalidaException: Senha Inválida!
    at Metodo1.autenticar(Metodo1.java:15)
    at Metodo1.main(Metodo1.java:4)
    
11.05.2017 / 15:37