System.setProperty设置值的存储位置及设置后未生效问题排查
问题描述
请问System.setProperty设置的属性值存储在何处?以下是示例代码:
public class LoadLogPropertiesFile { static { // must set before the Logger String path = LoadLogPropertiesFile.class.getClassLoader().getResource("logging.properties").getFile(); System.setProperty("java.util.logging.config.file", path); } private static Logger logger = Logger.getLogger(LoadLogPropertiesFile.class.getName()); public static void main(String[] args) { ... }
如上述代码所示,这段代码会设置键为java.util.logging.config.file的系统属性,对吗?根据文档说明:
This may result in a SecurityException being thrown. If no exception
is thrown, the specified property is set to the given value.
实际执行时未抛出SecurityException,但代码执行完毕后却检测不到指定名称的系统属性,请问这是什么原因?
回答
1. System.setProperty设置的属性存储位置
System.setProperty设置的系统属性存储在JVM维护的全局Properties集合中,这个集合是进程级别的全局共享资源,可通过System.getProperty(String key)或System.getProperties()方法直接访问。该属性会一直存在于JVM运行期间,除非被显式调用System.clearProperty(String key)清除,或被System.setProperty覆盖。
2. 属性设置后无法检测到的可能原因
针对你遇到的java.util.logging.config.file属性消失的问题,主要有以下几种可能:
日志系统初始化时的特殊处理
java.util.logging.config.file是Java日志框架(JUL)的专用配置属性,当LogManager(日志系统的核心类)第一次初始化时(通常是首次调用Logger.getLogger()时),会读取该属性加载配置文件。部分JDK实现中,LogManager在完成配置加载后,会主动清除该属性,避免后续重复加载配置,这就会导致你后续检测不到该属性。静态初始化顺序的隐性问题
虽然你的代码中静态代码块写在logger静态变量之前,但如果存在其他隐性依赖(比如父类的静态初始化逻辑触发了Logger的初始化,或项目中其他类提前初始化了JUL日志系统),会导致LogManager在你的静态代码块设置属性之前就完成了初始化。这种情况下,属性确实被设置了,但日志系统并未使用它,且如果LogManager有清除属性的逻辑,后续也会看不到该属性。其他代码的修改/清除操作
检查你的main方法或其他异步执行的代码中,是否存在调用System.clearProperty("java.util.logging.config.file")或System.setProperty将该属性设为null的逻辑,这类操作会直接移除或覆盖你设置的属性值。
内容的提问来源于stack exchange,提问作者rozerro

