6
At first an operating system works with 3 rows System.err
(flow output for standard error stderr), System.out
(standard flow output stdout) and System.in
(stdin data input)
When using the PrintStackTrace
, he writes by default on System.err
and also informs a cell trace, ie 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 example System.out
print on the console and System.err
write to a file for example.
With respect to 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 by OS.
You will see that at each run it will change the order of the queues but the instruction order for the queue will not, the printing for stdout
follow the sequence (1, 2, 3) and to stderr
also (1, 2, 3) but the order it will display the queue will not respect this sequence (stdout, stderr)
There is a way to synchronize the two queues, however 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 earlier syserr 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 yes the application will respect the sequence stdout (1, 2, 3), stderr (1, 2, 3) and also the sequence of the queues (stdout, stderr)
When you log many things at the same time (I know in your case it was just an instruction), it can happen from one message to "cross" the other...
– Erick Maia
Look at this question http://stackoverflow.com/questions/19460987/why-is-system-out-prinln-out-of-order
– Erick Maia