Module java.logging

Class LogManager

java.lang.Object
java.util.logging.LogManager

public class LogManager extends Object
有一个单一的全局LogManager对象,用于维护关于Loggers和日志服务的一组共享状态。

这个LogManager对象:

  • 管理Logger对象的分层命名空间。所有命名的Loggers都存储在这个命名空间中。
  • 管理一组日志控制属性。这些是简单的键值对,可以被Handlers和其他日志对象用来配置自己。

全局LogManager对象可以使用LogManager.getLogManager()来检索。LogManager对象在类初始化期间创建,随后不能更改。

在启动时,LogManager类使用java.util.logging.manager系统属性进行定位。

LogManager配置

LogManager在LogManager初始化期间通过readConfiguration()方法初始化日志配置。默认情况下,使用LogManager默认配置。LogManager读取的日志配置必须采用properties文件格式。

LogManager定义了两个可选的系统属性,允许通过readConfiguration()方法控制初始配置:

  • java.util.logging.config.class
  • java.util.logging.config.file

这两个系统属性可以在"java"命令的命令行上指定,或作为传递给JNI_CreateJavaVM的系统属性定义。

用于Loggers和Handlers的properties将以处理程序或记录器的点分隔名称开头。
全局日志属性可能包括:

  • 一个属性"handlers"。这定义了一个空格或逗号分隔的类名列表,用于加载和注册作为根Logger(名为""的Logger)的处理程序类。每个类名必须是具有默认构造函数的Handler类。请注意,这些Handlers可能在首次使用时懒惰地创建。
  • 一个属性"<logger>.handlers"。这定义了一个空格或逗号分隔的类名列表,用于加载和注册作为指定记录器的处理程序类。每个类名必须是具有默认构造函数的Handler类。请注意,这些Handlers可能在首次使用时懒惰地创建。
  • 一个属性"<logger>.handlers.ensureCloseOnReset"。这定义了一个布尔值。如果"<logger>.handlers"未定义或为空,则忽略此属性。否则,默认为true。当值为true时,与记录器关联的处理程序将在重置和关闭时被关闭。可以通过在配置中显式设置"<logger>.handlers.ensureCloseOnReset=false"来关闭此功能。请注意,关闭此属性会增加引入资源泄漏的风险,因为记录器可能在调用reset()之前被垃圾回收,从而阻止其处理程序在reset()上被关闭。在这种情况下,应用程序有责任确保在记录器被垃圾回收之前关闭处理程序。
  • 一个属性"<logger>.useParentHandlers"。这定义了一个布尔值。默认情况下,每个记录器除了处理日志消息本身外,还调用其父记录器,这通常导致消息也被根记录器处理。将此属性设置为false时,需要为此记录器配置一个处理程序,否则不会传递任何日志消息。
  • 一个属性"config"。此属性旨在允许运行任意配置代码。该属性定义了一个空格或逗号分隔的类名列表。将为每个命名类创建一个新实例。每个类的默认构造函数可以执行任意代码来更新日志配置,例如设置记录器级别、添加处理程序、添加过滤器等。

请注意,在LogManager配置期间加载的所有类首先在系统类路径上搜索,然后在任何用户类路径上搜索。这包括LogManager类、任何配置类和任何处理程序类。

记录器根据其点分隔名称的命名层次结构进行组织。因此,"a.b.c"是"a.b"的子级,但"a.b1"和"a.b2"是同级。

所有名称以".level"结尾的属性都被假定为定义Loggers的日志级别。因此,"foo.level"为名为"foo"的记录器及其(递归地)任何子级定义了日志级别。日志级别按照它们在properties文件中定义的顺序应用。因此,树中子节点的级别设置应该在其父节点的设置之后。属性名称".level"可用于设置树的根的级别。

LogManager对象上的所有方法都是多线程安全的。

自:
1.4
  • Field Details

  • Constructor Details

    • LogManager

      protected LogManager()
      受保护的构造函数。这是受保护的,以便容器应用程序(如J2EE容器)可以对对象进行子类化。它是非公共的,因为只应该有一个LogManager对象,其值通过调用LogManager.getLogManager来检索。
  • Method Details

    • getLogManager

      public static LogManager getLogManager()
      返回全局LogManager对象。
      返回:
      全局LogManager对象
    • addLogger

      public boolean addLogger(Logger logger)
      添加一个命名记录器。如果已经注册了具有相同名称的记录器,则此操作不执行任何操作并返回false。

      Logger工厂方法调用此方法来注册每个新创建的Logger。

      应用程序应保留对Logger对象的引用,以避免其被垃圾回收。LogManager可能仅保留一个弱引用。

      参数:
      logger - 新记录器。
      返回:
      如果成功注册参数记录器,则返回true;如果已存在具有该名称的记录器,则返回false。
      抛出:
      NullPointerException - 如果记录器名称为null。
    • getLogger

      public Logger getLogger(String name)
      查找一个命名记录器的方法。

      请注意,由于不受信任的代码可能使用任意名称创建记录器,因此不应依赖此方法来查找用于安全敏感日志记录的记录器。还要注意,与字符串name关联的Logger可能随时被垃圾回收,如果没有对Logger的强引用。调用此方法的调用者必须检查返回值是否为null,以正确处理Logger已被垃圾回收的情况。

      参数:
      name - 记录器的名称
      返回:
      匹配的记录器,如果找不到则返回null
    • getLoggerNames

      public Enumeration<String> getLoggerNames()
      获取已知记录器名称的枚举。

      注意:随着新类的加载,记录器可能会动态添加。此方法仅报告当前注册的记录器。还要注意,此方法仅返回Logger的名称,而不是Logger本身的强引用。返回的字符串无法防止Logger被垃圾回收。特别是,如果返回的名称传递给LogManager.getLogger(),则调用者必须检查从LogManager.getLogger()返回的值是否为null,以正确处理Logger在其名称被此方法返回后被垃圾回收的情况。

      返回:
      记录器名称字符串的枚举
    • readConfiguration

      public void readConfiguration() throws IOException, SecurityException
      读取并初始化日志配置。

      如果设置了"java.util.logging.config.class"系统属性,则该属性值将被视为类名。将加载给定的类,实例化一个对象,该对象的构造函数负责读取初始配置。(该对象可以使用其他系统属性来控制其配置。)备用配置类可以使用readConfiguration(InputStream)来定义LogManager中的属性。

      如果未设置"java.util.logging.config.class"系统属性,则此方法将从属性文件中读取初始配置,并调用readConfiguration(InputStream)方法来初始化配置。可以使用"java.util.logging.config.file"系统属性来指定要读取的属性文件作为初始配置;如果未设置,则将使用LogManager的默认配置。默认配置通常从Java安装目录中的属性文件"conf/logging.properties"中加载。

      在读取属性后,将调用任何注册的配置监听器

      API注释:
      readConfiguration方法应仅用于在LogManager初始化期间初始化配置或与"java.util.logging.config.class"属性一起使用。当在创建记录器之后调用此方法,并且未设置"java.util.logging.config.class"系统属性时,所有现有记录器将被重置。然后,任何在新配置流中指定了级别属性的现有记录器将被设置为指定的日志级别。

      要正确更新日志配置,请改用updateConfiguration(java.util.function.Function)updateConfiguration(java.io.InputStream, java.util.function.Function)方法。

      抛出:
      SecurityException - 如果存在安全管理器并且调用方没有LoggingPermission("control")。
      IOException - 如果读取配置时出现IO问题。
    • reset

      public void reset() throws SecurityException
      重置日志配置。

      对于所有命名记录器,重置操作将删除并关闭所有处理程序,并(除根记录器外)将级别设置为null。根记录器的级别设置为Level.INFO

      API注释:
      调用此方法还会清除LogManager的属性。可以使用updateConfiguration(Function)updateConfiguration(InputStream, Function)方法来正确更新到新配置。
      抛出:
      SecurityException - 如果存在安全管理器并且调用方没有LoggingPermission("control")。
    • readConfiguration

      public void readConfiguration(InputStream ins) throws IOException, SecurityException
      从给定的输入流读取并初始化日志配置。

      在读取属性后,将调用任何注册的配置监听器

      API注释:
      readConfiguration方法应仅用于在LogManager初始化期间初始化配置或与"java.util.logging.config.class"属性一起使用。当在创建记录器之后调用此方法时,所有现有记录器将被重置。然后,任何在给定输入流中指定了级别属性的现有记录器将被设置为指定的日志级别。

      要正确更新日志配置,请改用updateConfiguration(java.util.function.Function)updateConfiguration(java.io.InputStream, java.util.function.Function)方法。

      参数:
      ins - 从中读取属性的流
      抛出:
      SecurityException - 如果存在安全管理器并且调用方没有LoggingPermission("control")。
      IOException - 如果读取配置时出现问题,或者给定的流不符合属性文件格式。
    • updateConfiguration

      public void updateConfiguration(Function<String,BiFunction<String,String,String>> mapper) throws IOException
      更新日志配置。

      如果设置了"java.util.logging.config.file"系统属性,则该属性值指定要作为新配置读取的属性文件。否则,将使用LogManager的默认配置。
      默认配置通常从Java安装目录中的属性文件"conf/logging.properties"中加载。

      此方法读取新配置并调用updateConfiguration(ins, mapper)方法来更新配置。

      API注释:
      此方法从读取属性文件更新日志配置,并忽略"java.util.logging.config.class"系统属性。"java.util.logging.config.class"属性仅由readConfiguration()方法用于加载自定义配置类作为初始配置。
      参数:
      mapper - 一个函数接口,接受配置键k并返回一个函数f(o,n),其返回值将应用于生成的配置。函数f可以返回null以指示属性k不会添加到生成的配置中。
      如果mappernull,则假定为(k) -> ((o, n) -> n)
      对于每个k,将使用与旧配置中关联的k的值(即o)和与新配置中关联的k的值(即n)调用映射函数f
      对于onnull值表示在相应配置中不存在k的值。
      抛出:
      SecurityException - 如果存在安全管理器并且调用方没有LoggingPermission("control"),或者没有设置配置所需的权限(例如,打开为FileHandlers指定的文件等)。
      NullPointerException - 如果mapper在调用时返回null函数。
      IOException - 如果从日志配置文件读取时出现问题。
      自:
      9
      参见:
    • updateConfiguration

      public void updateConfiguration(InputStream ins, Function<String,BiFunction<String,String,String>> mapper) throws IOException
      更新日志配置。

      对于现有配置中的每个配置键和给定的输入流配置,将调用给定的mapper函数,将配置键映射到一个函数f(o,n),该函数接受旧值和新值,并返回要应用于结果配置中的结果值,如下表所示。

      k是旧配置或新配置中的配置键,o是旧值(即与旧配置中的k关联的值),n是新值(即与新配置中的k关联的值),f是由mapper.apply(k)返回的函数:那么v = f(o,n)是结果值。如果v不是null,则将向结果配置中添加一个值为v的属性k。否则,将被省略。
      可以向函数f传递null值,以指示相应配置中没有配置键k。函数f可以返回null,以指示结果配置中不会有与k关联的值。

      如果mappernull,则v将设置为n

      LogManager中的属性将使用结果值进行更新。

      成功更新配置后,将调用注册的配置监听器

      更新配置属性
      属性 结果行为
      <logger>.level
      • 如果结果配置为记录器定义了级别,并且结果级别与旧配置中指定的级别不同,或者在旧配置中未指定级别,则如果记录器存在或该记录器的子记录器存在,则将更新该记录器的级别,并将更改传播到任何现有记录器子记录器。如果需要,这可能会导致创建记录器。
      • 如果旧配置为记录器定义了级别,并且结果配置没有定义级别,则不会将此更改传播到现有记录器(如果有)。要完全替换配置 - 因此在调用updateConfiguration之前,调用者应首先调用reset以清空当前配置。
      <logger>.useParentHandlers
      • 如果useParentHandlers属性的结果值或旧值不为null,则如果记录器存在或该记录器的子记录器存在,则该记录器将更新为结果值。useParentHandlers属性的值是配置中指定的值;如果未指定,则默认值为true。
      <logger>.handlers
      • 如果结果配置为记录器定义了处理程序列表,并且结果列表与旧配置中为该记录器指定的列表不同(可能为空),则如果记录器存在或其子记录器存在,则与该记录器关联的处理程序将被关闭和删除,并将根据结果配置创建新处理程序,并将其添加到该记录器中,如有必要创建该记录器。
      • 如果旧配置为记录器定义了一些处理程序,并且结果配置没有定义处理程序,则如果该记录器存在,则其处理程序将被删除并关闭。
      • 更改现有记录器上的处理程序列表将导致删除和关闭其先前的所有处理程序,无论这些处理程序是从配置还是以编程方式创建的。旧处理程序将被新处理程序替换,如果有的话。
      <handler-name>.*
      • 在处理程序类上配置/更改的属性仅会影响新创建的处理程序。如果一个节点在旧配置和结果配置中配置了相同的处理程序列表,则这些处理程序将保持不变。
      config和任何其他属性
      • 这些属性的结果值将存储在LogManager属性中,但updateConfiguration不会解析或处理它们的值。

      示例映射函数:

      • 用新配置替换所有日志属性:

        (k) -> ((o, n) -> n):

        这相当于传递一个空的mapper参数。
      • 合并新配置和旧配置,并在新配置中存在k时使用新值:

        (k) -> ((o, n) -> n == null ? o : n):

        就像合并两个集合一样: result.putAll(oldc); result.putAll(newc)
      • 合并新配置和旧配置,并在旧配置中存在k时使用旧值:

        (k) -> ((o, n) -> o == null ? n : o):

        就像合并两个集合一样: result.putAll(newc); result.putAll(oldc)
      • 用新配置替换所有属性,但不包括用于配置非根记录器的处理程序属性:
        (k) -> k.endsWith(".handlers")
                  ? ((o, n) -> (o == null ? n : o))
                  : ((o, n) -> n)
      reset完全删除旧配置,然后调用 updateConfiguration初始化新配置。

      参数:
      ins - 用于读取属性的流
      mapper - 一个函数接口,接受配置键k并返回一个函数f(o,n),其返回值将应用于结果配置。函数f可以返回null,以指示属性k不会添加到结果配置中。
      如果mappernull,则假定为(k) -> ((o, n) -> n)
      对于每个k,将使用映射函数f与旧配置中与k关联的值(即o)和新配置中与k关联的值(即n)调用。
      onnull值表示相应配置中不存在值k
      抛出:
      SecurityException - 如果存在安全管理器并且调用者没有LoggingPermission("control"),或者没有设置配置所需的权限(例如为FileHandlers指定的打开文件)
      NullPointerException - 如果ins为null或者当调用mapper时返回一个空函数。
      IOException - 如果从流中读取时出现问题,或者给定流不符合properties文件格式。
      自:
      9
    • getProperty

      public String getProperty(String name)
      获取日志属性的值。如果未找到属性,则该方法返回null。
      参数:
      name - 属性名称
      返回:
      属性值
    • checkAccess

      @Deprecated(since="17", forRemoval=true) public void checkAccess() throws SecurityException
      Deprecated, for removal: This API element is subject to removal in a future version.
      This method is only useful in conjunction with the Security Manager, which is deprecated and subject to removal in a future release. Consequently, this method is also deprecated and subject to removal. There is no replacement for the Security Manager or this method.
      检查当前上下文是否受信任以修改日志配置。这需要LoggingPermission("control")。

      如果检查失败,我们将抛出SecurityException,否则我们将正常返回。

      抛出:
      SecurityException - 如果存在安全管理器并且调用者没有LoggingPermission("control")。
    • getLoggingMXBean

      @Deprecated(since="9") public static LoggingMXBean getLoggingMXBean()
      Deprecated.
      java.util.logging.LoggingMXBean is deprecated and replaced with java.lang.management.PlatformLoggingMXBean. Use ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class) instead.
      返回用于管理记录器的LoggingMXBean
      返回:
      一个LoggingMXBean对象。
      自:
      1.5
      参见:
    • addConfigurationListener

      public LogManager addConfigurationListener(Runnable listener)
      添加配置监听器,以便在每次读取日志配置时调用。如果监听器已注册,则该方法不执行任何操作。

      监听器以调用此方法的调用上下文限制的权限调用。调用监听器的顺序是未指定的。

      建议监听器不要抛出错误或异常。如果监听器以未捕获的错误或异常终止,则第一个异常将在调用readConfiguration()(或readConfiguration(java.io.InputStream))后,所有监听器被调用后传播给调用者。

      实现说明:
      如果多个监听器以未捕获的错误或异常终止,实现可能将其他错误或异常记录为抑制异常
      参数:
      listener - 在更改配置后将被调用的配置监听器。
      返回:
      此LogManager。
      抛出:
      SecurityException - 如果存在安全管理器并且调用者没有LoggingPermission("control")。
      NullPointerException - 如果监听器为null。
      自:
      9
    • removeConfigurationListener

      public void removeConfigurationListener(Runnable listener)
      删除先前注册的配置监听器。如果未找到监听器,则静默返回。
      参数:
      listener - 要移除的配置监听器。
      抛出:
      NullPointerException - 如果监听器为null。
      SecurityException - 如果存在安全管理器且调用者没有LoggingPermission("control")。
      自从:
      9