昨天遇到了一个 System.out 与 Throwable.printStackTrace() 输出信息顺序错乱的问题。
现场还原
首先我调用 System.out 输出普通字符串
1 | Time: 0.2 |
然后再调用 Throwable.printStackTrace() 输出异常信息
1 | java.lang.NoSuchMethodException: test.MathTest.ok() |
正常来说应该能得到如下输出内容
1 | Time: 0.2 |
但是有时候多运行几次代码会得到错乱的信息
1 | Time: 0.2 |
System.out 与 Throwable.printStackTrace() 的输出内容混在一起了,没有按照顺序来输出
原因
问了别人,说是因为 System.out 和 System.err 的输出顺序问题。于是查看了下 Throwable.printStackTrace() 的源码。发现 Throwable.printStackTrace() 会调用 System.err 进行内容输出
1 | public void printStackTrace() { |
再查看网上的解释,System.out 是有缓冲区的,JVM 和操作系统会等待缓冲区中的内容达到一定的大小再输出内容。而 System.err 的话,是没有缓冲区这种东西,有内容就立刻输出。所以造成了 System.out 与 Throwable.printStackTrace() 的输出内容混在一起了。这就是原因。
如何解决
根据 Throwable.printStackTrace() 的源码
1 | public void printStackTrace() { |
只需要调用 printStackTrace(PrintStream s) 传入 System.err 即可,也就是调用 Throwable.printStackTrace(System.err)。
这样输出内容再也不会顺序错乱了。