实际上这是一个JDK的bug。多年来曾有多次报告,但直到8139507,Oracle才真正重视此问题。
问题出现在WindowsPreferences.java
的JDK源代码中。在这个类中,userRoot
和systemRoot
两个节点都被声明为静态,如下所示:
/**
* User root node.
*/
static final Preferences userRoot =
new WindowsPreferences(USER_ROOT_NATIVE_HANDLE, WINDOWS_ROOT_PATH);
/**
* System root node.
*/
static final Preferences systemRoot =
new WindowsPreferences(SYSTEM_ROOT_NATIVE_HANDLE, WINDOWS_ROOT_PATH);
这意味着第一次引用该类时,会初始化两个静态变量,并尝试创建HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs
(=系统树)的注册表键,如果它还不存在。
因此,即使用户在自己的代码中采取了每一个预防措施,从不触及或引用系统树,JVM实际上仍会尝试实例化systemRoot
,从而导致警告。这是一个有趣的微妙错误。
JDK源代码修复于2016年6月提交,从Java9开始就已经包含在内了。Java8也有一个回退版本,在u202中。
你看到的只是JDK内部记录器的一个警告,不是异常。我相信这个警告可以安全地忽略......除非用户代码确实需要系统首选项,但这种情况很少见。
额外信息
这个错误在Java 1.7.21之前的版本中没有显露出来,因为在那之前JRE安装程序会为您创建注册表键HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs
,从而有效地隐藏了这个错误。另一方面,您实际上并不需要运行安装程序才能在计算机上拥有JRE,或者至少这不是Sun/Oracle的意图。就像你可能知道的那样,Oracle多年来一直以.tar.gz
格式分发Windows版JRE。