在运行时设置java.util.logging.config.file

12
我正在尝试在运行时设置Java util日志配置文件,以避免将其设置为VM参数。 但这并不起作用。每当我尝试重新读取配置时,日志记录就完全停止了。
请参阅以下代码片段:
package test;

import java.io.FileInputStream;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

public class A {
  private static final Logger LOGGER= Logger.getLogger(A.class.getName());

  public static void main(String[] args) throws Exception {
    System.out.println("--- start");
    LOGGER.log(Level.SEVERE, "SEVERE 1");
    LOGGER.log(Level.FINEST, "FINEST 1");
    LogManager.getLogManager().readConfiguration();
    LOGGER.log(Level.SEVERE, "SEVERE 2");
    LOGGER.log(Level.FINEST, "FINEST 2");
    LogManager.getLogManager().readConfiguration(new FileInputStream("/tmp/logging.properties"));
    LOGGER.log(Level.SEVERE, "SEVERE 3");
    LOGGER.log(Level.FINEST, "FINEST 3");
    System.out.println("--- end");
  }
}

如果我不使用任何VM参数运行该类,则输出如下:
--- start
09.11.2012 09:59:25 test.A main
SCHWERWIEGEND: SEVERE 1
09.11.2012 09:59:25 test.A main
SCHWERWIEGEND: SEVERE 2
--- end

如您所见,仅记录SEVERE级别的日志,因为这是JRE logging.properties 的默认设置。调用LogManager#readConfiguration()不会改变任何内容。但是,在尝试从我的logging.properties读取配置时,绝对没有记录任何内容。使用LogManager#readConfiguration(InputStream)或设置java.util.logging.config.file属性并调用LogManager#readConfiguration()没有任何区别。
现在请看下一行输出,当我使用VM属性-Djava.util.logging.config.file=/tmp/logging.properties运行相同的代码时:
--- start
2012-11-09 10:03:44.0838 SEVERE  [test.A#main()] - SEVERE 1
2012-11-09 10:03:44.0843 FINEST  [test.A#main()] - FINEST 1
--- end

正如您所看到的,SEVERE和FINEST级别都已记录,并以不同的格式记录。 两者都在我的自定义logging.properties中指定。 但是在调用LogManager#readConfiguration()后,日志记录就停止了! 这与上面的示例不同,我不明白原因。 此外,与上面的示例一样,调用LogManager#readConfiguration(InputStream)也无法正常工作。
那么问题出在哪里呢? 根据 javadoc,在运行时设置java.util.logging.config.file属性应该可以解决问题。并且我期望两个readConfiguration()方法都能正常工作。 那么问题出在哪里呢?

1
这可能会对您有所帮助:https://dev59.com/fm015IYBdhLWcg3w6QLA - Captain Obvious
不,这并没有帮助。也许我误解了你的建议,但是那个问题及其答案都是关于完全以编程方式配置记录器的。我想使用logging.properties文件,但在运行时读取它(因为我不想在命令行设置VM参数)。另外,让我困惑的是,readConfiguration()方法似乎没有做它们应该做的事情。 - radlan
我已经测试过了,它对我有效。readConfiguration()读取配置后,新的日志记录器配置将被使用。JDK 1.6.0_27. - Udo Klimaschewski
我尝试过JDK 1.6.0_26,1.6.0_31和1.7.0_07。都是在Linux下进行的。但它们都没有起作用。你试过我上面的代码片段了吗?如果是,请问输出结果是什么?如果不是,你能提供一个你成功运行的例子吗?这样我就可以试着将其应用到我的问题上了。 - radlan
2个回答

6

可能是您的日志属性出了问题。我注意到,在配置文件中(根和控制台),必须同时使用级别说明才能得到结果。
也许您的根记录器级别低于FINEST,例如INFO (.level=INFO)。
或者根本没有设置,那么我假设它是INFO

我使用以下logging.properties运行了您的代码:

handlers=java.util.logging.ConsoleHandler
.level=FINEST
java.util.logging.ConsoleHandler.level=FINEST

如果不指定-Djava.util.logging.config.file=/tmp/logging.properties,输出结果如下:

--- start
09.11.2012 14:25:49 testing.Scribble main
SCHWERWIEGEND: SEVERE 1
09.11.2012 14:25:49 testing.Scribble main
SCHWERWIEGEND: SEVERE 2
09.11.2012 14:25:49 testing.Scribble main
SCHWERWIEGEND: SEVERE 3
09.11.2012 14:25:49 testing.Scribble main
AM FEINSTEN: FINEST 3
--- end

看起来正确!(我的测试类名为testing.Scribble,这是唯一的区别)

使用-Djava.util.logging.config.file=/tmp/logging.properties输出如下:

--- start
09.11.2012 14:31:06 testing.Scribble main
SCHWERWIEGEND: SEVERE 1
09.11.2012 14:31:06 testing.Scribble main
AM FEINSTEN: FINEST 1
09.11.2012 14:31:06 testing.Scribble main
SCHWERWIEGEND: SEVERE 2
09.11.2012 14:31:06 testing.Scribble main
AM FEINSTEN: FINEST 2
09.11.2012 14:31:06 testing.Scribble main
SCHWERWIEGEND: SEVERE 3
09.11.2012 14:31:06 testing.Scribble main
AM FEINSTEN: FINEST 3
--- end

看起来也是正确的!


1
你说得对。问题出在我的logging.properties文件上。是handlers指令的问题。在我的logging.properties文件中,我在它前面写了一个点:.handlers。去掉这个点后,它就可以正常工作了。但让我困惑的是,当通过VM参数设置时,完全相同的logging.properties文件却可以正常工作。这很奇怪(我会称之为一个bug)。 - radlan

0

不要使用需要绝对或相对文件系统路径的 java.util.logging.config.file,你可以使用 java.util.logging.config.class,它会从类路径中加载一个类。

在 Gradle 构建中:

subprojects {
    // JavaForkOptions is base interface for JavaExec, BootRun, Test tasks...
    tasks.withType(JavaForkOptions) {
        systemProperty("java.util.logging.config.class", "com.evil.JulBootstrap")
    }
}

JulBootstrap有一个简单的实现 - 一个无参构造函数:

public class JulBootstrap {
    public JulBootstrap() {
        final Logger rootLogger = Logger.getLogger("");
        rootLogger.setLevel(Level.FINER);
        // See SLF4JBridgeHandler.install().
        rootLogger.addHandler(new SLF4JBridgeHandler());
    }
}

你可以做一些花哨的事情,比如加载属性文件(可能还可以通过编程调整一些设置):
try (Inputstream stream : JulBootstrap.class.getResourceAsStream("/logging.properties")){
    LogManager.readConfiguration(stream);
}
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接