Cause runtime exceptions to be properly ordered with println in console output

拥有回忆 提交于 2019-12-05 03:13:15

A common problem with VM Java console output is that System.out and System.err are not usually synchronized properly,

No, they are synchronized perfectly. The problem is that the lines are intermixed because they are printed as separate calls to println(...). This is the code from Exception.printStackTrace():

        StackTraceElement[] trace = getOurStackTrace();
        for (int i=0; i < trace.length; i++)
            s.println("\tat " + trace[i]);

Loggers (like log4j) get the full stack trace and turn multiple lines into a single log output call which is then persisted atomically.

Why is this happening and what can be done to correct the problem?

Typically with Unix programs, standard-out is buffered while standard-error is not. I didn't think that this was true with Java but maybe it is. To read the javadocs of System.out:

The "standard" output stream. This stream is already open and ready to accept output data. Typically this stream corresponds to display output or another output destination specified by the host environment or user.

Versus for System.err:

By convention, this output stream is used to display error messages or other information that should come to the immediate attention of a user even if the principal output stream, the value of the variable out, has been redirected to a file or other destination that is typically not continuously monitored.

See this answer for more details: Why do System.err statements get printed first sometimes?

If this running the from the command line, you should redirect the out and err output to different files. Here's how to do that using ~unix:

How to redirect stderr and stdout to different files in the same line of bash?

In Java you can use System.setOut(...) and System.setErr(...) to send the different output to different PrintStreams so the lines don't interleave.


You edited the question to note that this is happening from inside an IDE. If you need to use System.out and err then you can redirect them using Java code above.

However, it is typical to use logging code instead. Common logging packages are log4j or logback which writes a single multi-line log message atomically to the output file so they don't get interleaved. As @fge mentions, there is also java.util.logging built into the JVM although the other packages provide more features.

Why is this happening and what can be done to correct the problem?

Because syserr and sysout are separate data streams but the system (IDE) console is trying to display both simultaneously. This can be fixed by using a Logger which will typically correctly order entries in the log.

Another possibility is to invoke System.setErr and assign it to a PrintStream for an error log file. This would be the Java equivalent solution to redirecting the error stream.

PyCharm also has this problem, which I believe uses the same IDE engine. There's a fix if you add the following line to your idea.properties file:

output.reader.blocking.mode=true

Get to idea.properties via Help | Edit Custom Properties.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!