为什么StreamHandler未捕获日志消息,对应代码运行断言失败?
问题根因
这段代码的核心问题是 java.util.logging.StreamHandler 默认采用带缓冲的输出逻辑,日志内容不会实时写入到传入的 ByteArrayOutputStream 中。
调用 log.info("test") 之后,日志内容仅被写入了 StreamHandler 的内部缓冲区,还没有被刷入到 baos 里,所以此时调用 baos.toByteArray() 拿到的是空数组,触发断言失败。
默认情况下 StreamHandler 只会在三种场景下把缓冲区内容刷入底层输出流:
- 内部缓冲区被写满
- StreamHandler 的
close()方法被调用 - 写入的日志等级高于等于 Handler 配置的
flushLevel(默认是Level.SEVERE,info 等级远低于这个阈值,不会触发自动 flush)
修复方案
可以选择以下任意一种方式解决:
- 手动调用 StreamHandler 的
flush()方法:
import java.io.ByteArrayOutputStream; import java.util.logging.SimpleFormatter; import java.util.logging.Logger; import java.util.logging.StreamHandler; Logger log = Logger.getLogger("foo"); log.setUseParentHandlers(false); ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 先持有Handler实例,不要直接匿名添加 StreamHandler handler = new StreamHandler(baos, new SimpleFormatter()); log.addHandler(handler); log.info("test"); handler.flush(); // 手动将缓冲区内容刷入baos assert baos.toByteArray().length > 0;
- 打印完日志后关闭 StreamHandler,close 操作会自动触发 flush:
log.info("test"); handler.close(); assert baos.toByteArray().length > 0;
- 自定义 StreamHandler 的
flushLevel为Level.INFO,这样 info 及以上等级的日志写入后会自动触发 flush。
内容的提问来源于stack exchange,提问作者yegor256
相关产品推荐
相关产品推荐

