跳到主要内容

JEP 264:平台日志 API 与服务

QWen Max 中英对照

概述

定义一个最小化的日志记录 API,平台类可以使用它来记录消息,并为这些消息的使用者提供一个服务接口。库或应用程序可以提供此服务的一个实现,以将平台日志消息路由到其所选择的日志框架。如果没有提供实现,则会使用基于 java.util.logging API 的默认实现。

目标

  • java.base 模块中定义和使用,因此它不能依赖于 java.util.logging API。

  • 易于被使用外部日志框架的应用程序采用,例如 SLF4JLog4J

  • 减少对 java.logging 模块的依赖,以简化 JDK 模块图。

  • 处理引导问题,以便平台类可以在日志消费者初始化之前记录消息。

  • 默认情况下,当 java.logging 模块存在时,通过 java.util.logging API 记录消息。

非目标

  • 定义一个通用的日志记录接口并不是目标。服务接口仅包含 JDK 自身使用所需的最小方法集合。

  • 通过 API 支持程序化日志配置(设置级别、目标文件等...)并不是目标。

  • 将 JDK 中的所有类转换为通过这个新 API 进行日志记录并不是目标。

动机

java.util.logging API 相比,大多数现代日志框架(例如 Log4J 2.0、Logback)都被划分为一个外观(facade)和一个实现部分。通过这样的外部框架进行日志记录的应用程序应当通过该框架提供的或支持的外观来创建记录器并执行日志记录操作。

所提出的服务使应用程序能够配置 JDK,以使用与应用程序相同的日志框架:它只需要提供该服务的一个实现,该实现返回包装了首选日志框架记录器的平台记录器。

该应用程序将继续使用其日志框架提供的外观。LoggerFinder 服务使得配置 JDK 使用相同的框架成为可能。

描述

使用 java.util.ServiceLoader API,通过系统类加载器定位并加载一个全局的 LoggerFinder 实现。如果没有找到具体的实现,则会使用 JDK 内部默认的 LoggerFinder 服务实现。当存在 java.logging 模块时,默认的服务实现会使用 java.util.logging 作为后端,因此默认情况下,日志消息会像以前一样路由到 java.util.logging.Logger。然而,LoggerFinder 服务使得应用程序或框架能够插入自己的外部日志后端,而无需同时配置 java.util.logging 和该后端。

LoggerFinder 服务的实现应能够区分系统记录器(由引导类加载器 (Bootstrap Class Loader, BCL) 中的系统类使用)和应用程序记录器(由应用程序创建供自己使用)。这种区分对于平台安全性非常重要。记录器的创建者可以将为其创建记录器的类或模块传递给 LoggerFinder,以便 LoggerFinder 能够确定要返回哪种类型的记录器。

JDK 中的类通过调用 System 类的工厂方法来获取从 LoggerFinder 创建的记录器:

package java.lang;

...

public class System {

System.Logger getLogger(String name) { ... }

System.Logger getLogger(String name, ResourceBundle bundle) { ... }

}

JDK 内部的 sun.util.logging.PlatformLogger API 将进行修订,以通过这些方法返回的系统记录器发出日志消息。

测试

将添加新的测试,以测试 LoggerFinder 服务以及到默认 java.util.logging 后端的映射。我们还需要验证插入现有的外部框架是否正常工作,特别是关于潜在的引导问题。

风险与假设

java.util.logging 作为后端时,已转换为使用系统记录器的 JDK 类应该仍然能够像以前一样通过 java.util.logging 进行配置,并且如果可能的话,不应更改日志消息和日志级别。

一些 Java SE API 当前在其公共签名中暴露了 java.util.logging 类型。这可能会成为将这些 API 转换为通过系统记录器进行日志记录的障碍。