VM Java控制台输出的一个常见问题是System.out和System.err通常不能正确同步,可能是因为它们位于不同的线程上。这导致混合输出,如下所示:
调试输出与运行时异常堆栈跟踪混淆
[8, 1, 3, 5, 9, 13, 15, 17, 19]
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
scanning xAnswer: 1 xValue: 1 total: 1 [1, 1, 0, 0, 0, 0, 0, 0, 0]
at cra.common.Group_jsc.listSubsetSum(Group_jsc.java:29)
scanning xAnswer: 2 xValue: 2 total: 4 [2, 1, 2, 0, 0, 0, 0, 0, 0]
at cra.common.Group_jsc.main(Group_jsc.java:12)
scanning xAnswer: 3 xValue: 3 total: 9 [3, 1, 2, 3, 0, 0, 0, 0, 0]
scanning xAnswer: 4 xValue: 4 total: 18 [4, 1, 2, 3, 4, 0, 0, 0, 0]
scanning xAnswer: 5 xValue: 5 total: 31 [5, 1, 2, 3, 4, 5, 0, 0, 0]
reset to xAnswer: 4 xValue: 5 total: 26 [4, 1, 2, 3, 5, 5, 0, 0, 0]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
scanning xAnswer: 5 xValue: 6 total: 41 [5, 1, 2, 3, 5, 6, 0, 0, 0]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
reset to xAnswer: 4 xValue: 6 total: 35 [4, 1, 2, 3, 6, 6, 0, 0, 0]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
scanning xAnswer: 5 xValue: 7 total: 52 [5, 1, 2, 3, 6, 7, 0, 0, 0]
reset to xAnswer: 4 xValue: 7 total: 45 [4, 1, 2, 3, 7, 7, 0, 0, 0]
scanning xAnswer: 5 xValue: 8 total: 64 [5, 1, 2, 3, 7, 8, 0, 0, 0]
reset to xAnswer: 4 xValue: 8 total: 56 [4, 1, 2, 3, 8, 8, 0, 0, 0]
Process finished with exit code 1
由于异常发生在进程结束时,我希望在程序中的所有println之后发生异常打印。为什么会发生这种情况以及如何解决问题呢?
(请注意,此特定示例来自IntelliJ的IDEA控制台,但在Eclipse和其他Java IDE中也会发生同样的事情)
VM Java控制台输出的一个常见问题是System.out和System.err通常不能正确同步,
不,他们完美同步。问题是线条是混合的,因为它们是作为单独的println(...)
调用打印的。这是来自Exception.printStackTrace()
的代码:
StackTraceElement[] trace = getOurStackTrace();
for (int i=0; i < trace.length; i++)
s.println("\tat " + trace[i]);
记录器(如log4j)获取完整的堆栈跟踪并将多行转换为单个日志输出调用,然后以原子方式保存。
为什么会发生这种情况以及如何解决问题呢?
通常使用Unix程序时,标准输出会被缓冲,而标准错误则不会。我不认为这对Java来说是真的,但也许就是这样。要阅读System.out
的javadoc:
“标准”输出流。此流已打开并准备接受输出数据。通常,该流对应于主机环境或用户指定的显示输出或另一输出目的地。
qazxsw poi的经文:
按照惯例,此输出流用于显示应立即引起用户注意的错误消息或其他信息,即使主要输出流(变量
System.err
的值)已重定向到文件或其他目标,即通常不会持续监控。
有关更多详细信息,请参阅此答案:out
如果从命令行运行,则应将out和err输出重定向到不同的文件。以下是使用~unix的方法:
在Java中,您可以使用How to redirect stderr and stdout to different files in the same line of bash?和System.setOut(...)
将不同的输出发送到不同的System.setErr(...)
s,这样线条就不会交错。
您编辑了这个问题,注意这是从IDE内部发生的。如果你需要使用PrintStream
和System.out
,那么你可以使用上面的Java代码重定向它们。
但是,通常使用日志代码。常见的日志包是err
或log4j,它以原子方式将单个多行日志消息写入输出文件,因此它们不会交错。正如@fge所提到的,虽然其他包提供了更多功能,但也有logback。
为什么会发生这种情况以及如何解决问题呢?
因为syserr和sysout是单独的数据流,但系统(IDE)控制台试图同时显示它们。这可以通过使用java.util.logging
built into the JVM来修复,Logger
通常会正确地对日志中的条目进行排序。
另一种可能性是调用System.setErr并将其分配给PrintStream
以获取错误日志文件。这将是重定向错误流的Java等效解决方案。
PyCharm也有这个问题,我认为它使用相同的IDE引擎。如果您将以下行添加到idea.properties
文件中,则有一个修复:
output.reader.blocking.mode=true
通过帮助到达idea.properties
编辑自定义属性。