我试图在运行时设置 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 级别,因为这是 JRElogging.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() 方法都应该按我的预期工作。那么问题出在哪里呢?
可能是您的日志属性有问题。我注意到我必须在配置中使用两个级别规范(根和控制台)才能获得结果。
也许您的根记录器级别低于
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
看起来也正确!
代替
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);
}
...