System.Logger 是 JDK 自带的、与具体日志框架无关的日志门面。这篇用真实运行回答:它默认走哪里、级别怎么映射、占位符怎么写、禁用时的开销,以及怎样用 LoggerFinder 把它接到自己的后端——并看到 JDK 自己也在用它。
Oct 05, 2026 6:31:31 PM Main main
INFO: 消息 level=INFO
Oct 05, 2026 6:31:31 PM Main main
WARNING: 消息 level=WARNING
Oct 05, 2026 6:31:31 PM Main main
SEVERE: 消息 level=ERROR
(RES) isLoggable:TRACE=false DEBUG=false INFO=true WARNING=true ERROR=true ALL=false OFF=true;Logger 实现类 sun.util.logging.internal.LoggingProviderImpl$JULWrapper;名字 demo.app [FINER] demo.app: 消息 level=TRACE
[FINE] demo.app: 消息 level=DEBUG
[INFO] demo.app: 消息 level=INFO
[WARNING] demo.app: 消息 level=WARNING
[SEVERE] demo.app: 消息 level=ERROR
(RES) isLoggable:TRACE=true DEBUG=true INFO=true WARNING=true ERROR=true ALL=true OFF=true;Logger 实现类 sun.util.logging.internal.LoggingProviderImpl$JULWrapper;名字 demo.app DEBUG 被禁用:1000 次 log(level, Supplier) 调用后 Supplier 被执行了 0 次
DEBUG 被禁用:1000 次 log(level, String) 里直接调用 expensive():被执行了 1000 次
INFO 启用:1000 次 log(level, Supplier):Supplier 被执行了 1000 次(且每次都会输出到 stderr) [INFO] 带占位符 A 和 42
[INFO] 用 %s 和 %d 占位
[INFO] 引号 '单引号' 与 x
[INFO] 3.14 与 0
[WARNING] 带异常
java.lang.IllegalStateException: 出错了
at Main.main(Main.java:22)
[INFO] 没有参数但含 {0}
[INFO] null
[INFO] p1 的参数是数组 DEBUG 被禁用,5,000,000 次调用:log(DEBUG, Supplier) 11 ms(每次约 2.1 ns)
DEBUG 被禁用,5,000,000 次调用:log(DEBUG, "x=" + i) 字符串拼接 54 ms(每次约 10.8 ns)
DEBUG 被禁用,5,000,000 次调用:log(DEBUG, "x={0}", i) 参数形式 12 ms(每次约 2.5 ns)
DEBUG 被禁用,5,000,000 次调用:if (isLoggable) log(...) 15 ms(每次约 3.1 ns)
DEBUG 被禁用,5,000,000 次调用:不调用(空循环) 11 ms(每次约 2.2 ns) 不带 System.exit:
[CUSTOM INFO] demo.app : 用自定义 LoggerFinder 记录的消息
[CUSTOM DEBUG] demo.app : DEBUG 级别的消息
[CUSTOM WARNING] other.name : 另一个 logger
finder = MyFinder
调用 System.exit(3),退出码 3:
[CUSTOM INFO] demo.app : 用自定义 LoggerFinder 记录的消息
[CUSTOM DEBUG] demo.app : DEBUG 级别的消息
[CUSTOM WARNING] other.name : 另一个 logger
finder = MyFinder
[CUSTOM DEBUG] java.lang.Runtime (模块 java.base) : Runtime.exit() called with status: 3 + 异常 java.lang.Throwable: Runtime.exit(3)