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?
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 forstdout
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)
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)