Throwable.printStackTrace()
将堆栈跟踪写入 PrintStream。JVM 进程的流和底层标准“错误”输出流可以通过以下方式重定向System.err
System.err
- 调用
System.setErr(),
它更改 了 .System.err
- 或通过重定向进程的错误输出流。错误输出流可能会重定向到文件/设备
- 其内容可能被人员忽略,
- 文件/设备可能无法进行日志轮换,推断在存档文件/设备的现有内容之前,需要重新启动进程才能关闭打开的文件/设备句柄。
- 或者文件/设备实际上会丢弃写入它的所有数据,就像 .
/dev/null
从上面推断,调用构成有效(不好/很好)的异常处理行为,只有Throwable.printStackTrace()
- 如果在应用程序的生存期内没有重新分配,
System.err
- 如果在应用程序运行时不需要日志轮换,
- 如果接受/设计,应用程序的日志记录实践是写入(和JVM的标准错误输出流)。
System.err
在大多数情况下,上述条件不满足。人们可能不知道JVM中运行的其他代码,并且无法预测日志文件的大小或进程的运行时持续时间,并且设计良好的日志记录实践将围绕在已知目标中编写“机器可解析”日志文件(记录器中更可取但可选的功能)来帮助提供支持。
最后,人们应该记住,的输出肯定会与其他写入的内容交错(甚至可能两者都重定向到同一文件/设备)。这是一个必须处理的烦恼(对于单线程应用程序),因为在此类事件中,围绕异常的数据不容易解析。更糟糕的是,多线程应用程序很可能会生成非常混乱的日志,因为这不是线程安全的。Throwable.printStackTrace()
System.err
System.out
Throwable.printStackTrace()
没有同步机制可以将堆栈跟踪的写入同步到多个线程同时调用时。解决此问题实际上需要您的代码在与 关联的监视器上进行同步(如果目标文件/设备相同,并且,如果目标文件/设备相同,则也同步),这是为日志文件健全性付出的沉重代价。举个例子,和 类负责将日志记录附加到控制台,在 提供的日志记录工具中;发布日志记录的实际操作是同步的 - 尝试发布日志记录的每个线程还必须在与实例关联的监视器上获取锁定。如果您希望使用 / 获得具有非交错日志记录的相同保证,则必须确保相同 - 消息以可序列化的方式发布到这些流中。System.err
Throwable.printStackTrace()
System.err
System.out
ConsoleHandler
StreamHandler
java.util.logging
StreamHandler
System.out
System.err
考虑到上述所有情况,以及实际上有用的非常有限的场景,通常证明调用它是一种不好的做法。Throwable.printStackTrace()
扩展前面一段的论点,与写入控制台的记录器结合使用也是一个糟糕的选择。这部分是由于记录器将在不同的监视器上同步,而您的应用程序将(可能,如果您不需要交错的日志记录)在不同的监视器上进行同步。当您在应用程序中使用写入同一目标的两个不同的记录器时,该参数也成立。Throwable.printStackTrace