Java: java.util.Preferences Failing

2022-08-31 14:45:33

我的程序将加密的产品密钥数据保存到具有类(系统首选项,而不是用户)的计算机中。问题是,在Windows和Linux上(尚未在OSX上进行测试,但可能是相同的),如果我没有使用管理员权限或管理员权限运行程序,则每当尝试读取或保存数据时,它都会发出异常或警告。java.util.Preferencessudo

显然,要求用户以管理员权限运行程序是不切实际的。理想情况下,我希望操作系统向用户请求权限。

这是非常愚蠢的,并且删除了一半的目的。如何解决这个问题?Preferences

以下是我需要的摘要:我需要我的程序向操作系统请求保存系统设置的权限。


这是错误信息

这是我尝试读取节点时的错误(因为该节点不存在):

Mar 18, 2011 9:41:15 AM java.util.prefs.WindowsPreferences <init>
WARNING: Could not create windows registry node Software\JavaSoft\Prefs\myapp at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
Mar 18, 2011 9:41:15 AM java.util.prefs.WindowsPreferences WindowsRegOpenKey1
WARNING: Trying to recreate Windows registry node Software\JavaSoft\Prefs\myapp at root 0x80000002.
Mar 18, 2011 9:41:15 AM java.util.prefs.WindowsPreferences openKey
WARNING: Could not open windows registry node Software\JavaSoft\Prefs\myapp at root 0x80000002. Windows RegOpenKey(...) returned error code 2.
Mar 18, 2011 9:41:15 AM java.util.prefs.WindowsPreferences WindowsRegOpenKey1
WARNING: Trying to recreate Windows registry node Software\JavaSoft\Prefs\myapp\subpackage at root 0x80000002.
Mar 18, 2011 9:41:15 AM java.util.prefs.WindowsPreferences openKey
WARNING: Could not open windows registry node Software\JavaSoft\Prefs\myapp\subpackage at root 0x80000002. Windows RegOpenKey(...) returned error code 2.

这就是我尝试写入节点时发生的情况:

Mar 18, 2011 9:43:11 AM java.util.prefs.WindowsPreferences WindowsRegOpenKey1
WARNING: Trying to recreate Windows registry node Software\JavaSoft\Prefs\myapp\subpackage at root 0x80000002.
Mar 18, 2011 9:43:11 AM java.util.prefs.WindowsPreferences openKey
WARNING: Could not open windows registry node Software\JavaSoft\Prefs\myapp\subpackage at root 0x80000002. Windows RegOpenKey(...) returned error code 2.

答案 1

不幸的是,您在这里得到的大多数答案都是错误的...至少轻微。从某种意义上说,症状正在治疗,而不是原因。

让我们回顾一下。Java首选项有两个“树”:用户树系统树。您可以将自己的后端写入 Java 首选项(称为支持存储),但很少有开发人员这样做,因此您最终会获得 JDK 的默认支持存储。在Windows平台上,这意味着Win注册表,更具体地说:

  • 用户树被写入(操作系统用户始终具有写入权限)HKEY_CURRENT_USER\Software\JavaSoft\Prefs
  • 系统树被写入(只有具有管理员权限的操作系统用户才具有写入权限)HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs

总而言之:只要您的代码不尝试使用系统树,您就应该没问题,并且不需要在操作系统级别分配权限。系统树用于“主机上的所有用户”,用户树用于特定的登录用户。在你的情况下,我相信你可以用用户树来满足,所以这真的是你的解决方案。不要搞砸权限,以管理员身份运行,以及什么都没有。

....但还有更多。假设您的代码故意不按照说明触及 Java 首选项系统树。然后,您仍然会在 Windows 上看到此警告:

WARNING [java.util.prefs]: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.

这是怎么回事呢?我给你错误的建议了吗?没有。和我在一起。

深入研究JDK源代码,您会发现0x80000002意味着HKLM,即Win注册表中不应触及的位置。您的代码从不引用系统树,但您仍然看到此警告!??(在这一点上,你一定是把所有的头发都扯掉了...就像我所做的那样)

好吧,这是真正存在JDK错误的罕见场合之一。你可以在我的这个答案中阅读更多关于它的信息,如果你对为什么微妙的错误可以在JDK中多年未被发现感兴趣,我鼓励你阅读。该错误自 JDK 1.4 以来一直存在,但最近才被修复,尚未向后移植到 JDK 8(更新:该修复程序现已向后移植到 JDK 的 8u192 版本)

最佳建议

  • 确保代码仅引用用户树,而不引用系统树。操作系统需要各种 privs 才能写入系统范围的位置,这是公平的。如果您确实需要写入这样的位置,那么除了分配 privs,以管理员身份执行或其他方式之外,真的没有其他解决方案。

  • 忽略该警告。一旦你使用Java 8 update 192或更高版本,它就会消失。可以安全地忽略该警告。

  • 或者,您可以尝试以编程方式将警告静音。它来自JDK的平台记录器,所以这样的东西应该可以工作,尽管我自己还没有尝试过:

      sun.util.logging.PlatformLogger platformLogger = PlatformLogger.getLogger("java.util.prefs");
      platformLogger.setLevel(PlatformLogger.Level.OFF);
    

答案 2

这个链接对我有用:

解决问题解决方法是以 登录并创建密钥administratorHKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs


推荐