
Log4j 2.11+ 支持微秒级时间精度,但需满足 JDK 9+、多版本 JAR(MR-JAR)启用、未被遮蔽(shaded)等前提条件;%d{DEFAULT_MICROS} 仅在正确环境下生效,否则回退至毫秒精度。
log4j 2.11+ 支持微秒级时间精度,但需满足 jdk 9+、多版本 jar(mr-jar)启用、未被遮蔽(shaded)等前提条件;`%d{default_micros}` 仅在正确环境下生效,否则回退至毫秒精度。
Log4j 2.x 自 2.11.0 版本起引入了对微秒级时间戳的原生支持,其核心机制依赖于 JVM 的底层时钟能力升级。关键在于 log4j-core 是一个多版本 JAR(Multi-Release JAR, MR-JAR):它在 META-INF/versions/9/ 下提供了专为 JDK 9+ 编译的 PreciseClock 实现,该实现基于 Clock.instant()(纳秒级系统时钟),可提供亚毫秒精度(通常达微秒级);而 JDK 8 兼容路径则使用 System.currentTimeMillis(),天然受限于毫秒分辨率。
因此,即使你已使用 Java 11 和 Log4j 2.20.0,若以下任一条件不满足,%d{DEFAULT_MICROS} 仍将输出形如 2023-07-27 15:13:11,848000 的“伪微秒”格式(后三位恒为 000):
- ✅ JDK 版本 ≥ 9:已满足(Java 11 符合);
- ✅ Log4j-core 为 MR-JAR 且未被破坏:需验证 JAR 文件结构是否保留
META-INF/versions/9/目录; - ❌ JAR 被 Shade/Maven Assembly 打包合并:Shade 插件默认会剥离
META-INF/versions/,导致 MR-JAR 失效,强制回退至 JDK 8 版本的PreciseClock; - ❌ 运行于老旧应用服务器(如 WebLogic 12.1.x、Tomcat :其类加载器不识别 MR-JAR,跳过高版本字节码;
- ⚠️ 操作系统时钟精度限制:Windows Server 2019 默认系统时钟分辨率为 ~15ms,虽不影响 Log4j 内部纳秒计数,但真实微秒差异可能受 OS 层制约(建议通过
System.nanoTime()辅助验证)。
验证与修复步骤
-
检查 MR-JAR 是否完整
解压log4j-core-2.20.0.jar,确认存在:jar -tf log4j-core-2.20.0.jar | grep "META-INF/versions/9" # 应输出类似:META-INF/versions/9/org/apache/logging/log4j/core/time/PreciseClock.class
-
避免 Shade 破坏 MR-JAR
若使用 Maven Shade Plugin,请显式保留 MR-JAR 结构:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <!-- 关键:启用多版本 JAR 支持 --> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> </plugin> -
确认运行时实际使用的 Clock 类型
启用 Log4j 内部调试日志(-Dlog4j2.debug=true),启动时将打印:DEBUG StatusLogger Using PreciseClock with Clock.instant() (JDK9+)
若显示
currentTimeMillis(),则说明 MR-JAR 未生效。 -
替代方案(兼容性兜底)
若无法启用 MR-JAR,可手动注入高精度时钟(需自定义Clock):import org.apache.logging.log4j.core.time.Clock; import org.apache.logging.log4j.core.time.SystemClock; // 在 Log4j 初始化前设置(如 static block) System.setProperty("log4j.Clock", MyHighResClock.class.getName());其中
MyHighResClock可封装System.nanoTime()与Instant.now()的组合逻辑(注意线程安全与时区处理)。
总结:Log4j 的微秒精度不是纯格式化问题,而是 JVM 时钟能力 + JAR 元数据 + 运行环境协同的结果。
%d{DEFAULT_MICROS}是“开关”,而非“魔法”——只有当PreciseClock成功加载 JDK 9+ 实现时,它才真正输出有意义的微秒值。务必优先排查 MR-JAR 完整性与类加载环境,再优化日志模式。

















