Java: java.util.Preferences Failing

Jonah picture Jonah · Mar 18, 2011 · Viewed 88.5k times · Source

My program saves encrypted product key data to the computer with the java.util.Preferences class (system preferences, not user). The problem is, on both Windows and Linux (haven't tested on OSX, but it's probably the same), if I don't run the program with sudo or with Administrator privileges, it emits an exception or warning whenever it tries to read or save the data.

Obviously requiring the user to run the program with Admin privileges would be impractical. Optimally, I'd like the operating system to ask the user for permission.

This is quite silly, and removes half the purpose of Preferences. How can this be fixed?

Here's a summary what I need: I need my program to ask for permission from the operating system to save system settings.


Here is the error information

Here's the error when the when I try to read a node (because the node doesn't exist):

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.

And this is what happens when I try to write to a node:

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.

Answer

peterh picture peterh · Feb 5, 2017

Unfortunately most of the answers you got here are wrong ... at least slightly. In the sense that the symptom is being treated, not the cause.

Let's recap. Java Preferences has two "trees": the user tree and the system tree. You can write your own backend to Java Preferences (called a backing store) but few developers do, so you end up with the JDK's default backing store. On a Windows platform this means the Win Registry, more specifically:

  • The user tree is written into HKEY_CURRENT_USER\Software\JavaSoft\Prefs (the OS user always has write access here)
  • The system tree is written into HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs (only an OS user with admin privs has write access here)

In summary: As long as your code doesn't attempt to use the system tree, you should be fine and shouldn't need to mess with assigning privileges at the OS level. The system tree is meant for "all users on the host" and the user tree is meant for the specific logged-in user. In your case I'm confident you can suffice with the user tree, so that is really your solution. Don't go messing with privileges, running as Administrator, and what not.

.... but there's more. Suppose your code deliberately doesn't touch the Java Preferences system tree, as instructed. You'll then still see this warning on Windows:

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

So what is going on? Did I give you the wrong advice ? Not really. Stay with me.

Diving into the JDK source code you'll see that 0x80000002 means HKLM, i.e. the place in the Win Registry that shouldn't be touched. Your code never references the system tree and yet you still see this warning !?? (At this point you must be ripping all your hair out ... as I did)

Well, this is one of the rare occasions where there really is a JDK bug. You can read more about it in this answer by me which I encourage you to read if you are interested in why subtle bugs can go undetected in the JDK for years. The bug has existed ever since JDK 1.4 but has only recently been fixed and not yet backported to JDK 8.

Best advice

  • Make sure your code only references the user tree, not the system tree. It is only fair that the OS requires all kinds of privs for you to write to a system-wide location. If you really need to write into such a location then there really is no other solution than assigning privs, executing as Administrator or what not.
  • Ignore the warning. It'll go away once you are on Java 9 or when Oracle decides to backport the bug fix into Java 8. The warning can safely be ignored.
  • Alternatively you can try to programmatically ignore the warning. It comes from the JDK's Platform Logger, so something like this should work, albeit I haven't tried it myself:

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