Java:java.util.Preferences失败

Jon*_*nah 65 java preferences

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

显然要求用户使用Admin权限运行程序是不切实际的.最理想的是,我希望操作系统向用户请求许可.

这是非常愚蠢的,并且消除了一半的目的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.
Run Code Online (Sandbox Code Playgroud)

当我尝试写入节点时会发生这种情况:

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.
Run Code Online (Sandbox Code Playgroud)

小智 42

这个链接对我有用:

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

  • 虽然这可能有用,但它似乎不是一个解决方案.我不会发布需要最终用户编辑其注册表的应用程序. (10认同)

pet*_*erh 42

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

让我们回顾一下.Java Preferences有两个"树":用户树系统树.您可以将自己的后端编写到Java Preferences(称为后备存储),但开发人员很少,因此您最终得到了JDK的默认后备存储.在Windows平台上,这意味着Win注册表,更具体地说:

  • 用户树被写入HKEY_CURRENT_USER\Software\JavaSoft\Prefs(操作系统用户总是对这里有写权限)
  • 系统树被写入HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs(只有一个操作系统的用户具有管理员PRIVS这里有写权限)

总结:只要您的代码不尝试使用系统树,您应该没问题,不应该在操作系统级别分配权限.系统树适用于"主机上的所有用户",而用户树适用于特定的登录用户.在您的情况下,我相信您可以满足用户树,因此这是您的解决方案.不要乱用特权,以管理员身份运行,什么不是.

....但还有更多.假设您的代码故意不按指示触摸Java Preferences系统树.然后,您仍会在Windows上看到此警告:

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

那么发生了什么?我给你错误的建议了吗?并不是的.跟我在一起.

深入了解JDK源代码,您将看到0x80000002表示HKLM,即Win Registry中不应触及的位置.您的代码从不引用系统树,但您仍然看到此警告!?? (此时你必须把所有的头发都撕掉......就像我做的那样)

嗯,这是真正存在JDK错误的罕见情况之一.你可以在这个答案中阅读更多关于它的内容,我鼓励你阅读,如果你对为什么在JDK中多年未检测到细微的bug感兴趣.该错误自JDK 1.4以来就已存在,但最近才被修复,尚未向JDK 8移植.

最好的建议

  • 确保您的代码仅引用用户树,而不是系统树.操作系统需要各种权限才能写入系统范围的位置,这是公平的.如果你真的需要写入这样的位置,那么除了分配privs,以管理员执行或不执行任何操作之外,确实没有其他解决方案.
  • 忽略警告.一旦您使用Java 9或者Oracle决定将错误修复程序反向移植到Java 8中,它就会消失.警告可以安全地被忽略.
  • 或者,您可以尝试以编程方式忽略警告.它来自JDK的Platform Logger,所以这样的东西应该可以工作,虽然我自己没有尝试过:

    sun.util.logging.PlatformLogger platformLogger = PlatformLogger.getLogger("java.util.prefs");
    platformLogger.setLevel(PlatformLogger.Level.OFF);
    
    Run Code Online (Sandbox Code Playgroud)


kue*_*000 11

可以更改注册表项的访问权限.如果您允许HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs每个人拥有完全访问权限 ,那么每个人都会看到相同的首选项,并且每个人都可以在全局范围内进行更改.我知道这不是客户安装的软件的解决方案,但它可能对某人有用.

  • 这就是我打算做的事情 - 向我的安装程序添加一个脚本,该脚本调用'regini'windows命令来设置特定键的权限.也许不是"HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs"的权限,而是我需要访问的Prefs中的特定节点. (2认同)

qwe*_*rty 5

根据反馈修改答案.这个解决方案可能有点过头但是......

  • 我建议你改变你的商店写一个文件而不是注册表(例子)
  • 许多基于Java的产品都附带了自己的JVM.他们这样做是为了让他们可以运行自定义策略文件(在您的情况下需要写入公共位置)并节省支持问题(如使用过时/未测试的JVM)