【问题标题】:Why do System.err statements get printed first sometimes?为什么有时会先打印 System.err 语句?
【发布时间】:2012-02-27 02:38:39
【问题描述】:

在 Java 中,我注意到有时,System.err 语句在 System.out 语句之前首先打印,尽管在我的代码中后者首先出现在前者之前。为什么?我很好奇。

【问题讨论】:

  • 从 1.02 开始,当我出于这个原因进行黑客攻击时,我一直坚持使用 System.err。不知道最新版本的 Java 表现如何,因为我没有对其进行测试。

标签: java stdout stderr


【解决方案1】:

通常,System.out 是一个缓冲输出流,因此文本在刷新到目标位置之前会被累积。这可以显着提高打印大量文本的应用程序的性能,因为它最大限度地减少了必须进行的昂贵系统调用的数量。但是,这意味着文本并不总是立即显示,并且可能会比写入的时间晚得多。

另一方面,System.err 通常不会被缓冲,因为需要立即打印错误消息。这是较慢的,但直觉是错误消息可能是时间关键的,因此程序减速可能是合理的。根据the Javadoc for System.err

通常,此流对应于主机环境或用户指定的显示输出或另一个输出目标。 按照惯例,此输出流用于显示错误消息或其他应立即引起用户注意的信息,即使主要输出流(变量 out 的值)已重定向到通常不会持续监控的文件或其他目标。

(我的重点)

但是,因此,发送到System.out 的旧数据可能会在更新的System.err 消息之后显示,因为旧的缓冲数据在消息发送到System.err 之前被刷新。例如这一系列事件:

  • “你好”被缓冲到System.out
  • “PANIC”直接发送到System.err 并立即打印。
  • “世界!”缓冲到System.out,并打印缓冲的数据

将导致输出

PANIC
Hello, world!

即使在PANIC 被打印到System.err 之前,Hello 被打印到 System.out

希望这会有所帮助!

【讨论】:

  • 只是出于好奇:当通过管道传输到终端时,java 是否做出与 C wrt stdout 相同的保证? IE。每次写入换行符时我们都会刷新缓冲区?
  • @Voo- 我只是查看了 Javadoc,似乎没有任何此类内容。
  • PrintStream 被实现为在几乎所有内容之后刷新(我认为您可以直接write 而不是)。
【解决方案2】:

它与缓冲和优先级有关。据推测,Java(如 C 和 C 衍生物)不会缓冲 System.errstderr 等,不像 System.outstdout 等。这样,系统可以确保您最有可能得到任何相关的错误消息,即使它出于某种原因不得不放弃标准输出。

来自Wikipedia

将标准输出和标准错误定向到相同的目的地是可以接受的,并且是正常的,例如文本终端。除非涉及缓冲,否则消息的出现顺序与程序写入它们的顺序相同。 (例如,一种常见的情况是标准错误流是无缓冲的,而标准输出流是行缓冲的;在这种情况下,如果标准输出流的缓冲区没有,则稍后写入标准错误的文本可能会更早出现在终端上还没满。)

【讨论】:

  • 我从不关心流的任何优先级.. 那是如何工作的?我会选择简单的缓冲解释。
  • 只是一个华丽的语言问题。固定为更具技术性:)
猜你喜欢
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 2019-12-23
相关资源
最近更新 更多