Skip to main content

Reading the Windows Registry from Java without JNI

June 19, 2009 by davidc

Here is a class that allows you to read the Windows Registry without having to install any JNI library. It is implemented purely using introspection and will therefore compile and run on any platform. It would be possible to extend this to also write to the registry, but I didn't need this functionality. I hesistate to call this "pure Java" as it does make native calls, but it does avoid the need for external dependencies to do so.

Operation

I forget who first pointed this out to me, but the java.util.prefs.WindowsPreferences implementation contains handy native methods to read and write any registry key, not just those under Software\Java\Prefs. By evil use of introspection, one can force these to be accessible and use them to read the registry without needing to install a new JNI library.

Figuring out which methods are needed and how to use them is a simple matter of tracing the getSpi() method in WindowsPreferences. From there, one can use the Method.setAccessible() method to bypass JVM security checks and execute them through introspection.

I have not implemented the write methods as I had no need for them, but they should be equally easy to do.

Caveats

Of course, this approach is pure evil*: breaking encapsulation and accessing private members is morally objectionable and liable to break under future versions. For my purposes, the requirement was not mission-critical. It works well enough and there will be no ill-effects if it fails in the future. On non-Windows platforms, or if the WindowsPreferences implementation changes, a BackingStoreException will be thrown.

However, if registry access is critical to your application, try something like JNIRegistry instead.

Code

package net.infotrek.util;
 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
 
/**
 * Very evil class to read from the Windows registry by breaking into the WindowsPreference
 * class methods and forcing them to be accessible.
 * <p/>
 * N.B. All access to WindowsPreferences (rather than just Preferences) must be through introspection,
 * as this class only exists on Windows platforms.
 *
 * @author David Croft (<a href="http://www.davidc.net">www.davidc.net</a>)
 * @version $Id: WindowsRegistry.java 285 2009-06-18 17:48:28Z david $
 */
@SuppressWarnings({"HardCodedStringLiteral", "StringConcatenation"})
public class WindowsRegistry
{
  /* Windows hives */
  public static final int HKEY_CURRENT_USER = 0x80000001;
  public static final int HKEY_LOCAL_MACHINE = 0x80000002;
 
  /* Windows security masks */
  private static final int KEY_READ = 0x20019;
 
  /* Constants used to interpret returns of native functions */
  private static final int NATIVE_HANDLE = 0;
  private static final int ERROR_CODE = 1;
 
  /* Windows error codes. */
  private static final int ERROR_SUCCESS = 0;
  private static final int ERROR_FILE_NOT_FOUND = 2;
 
  public static String getKeySz(int hive, String keyName, String valueName)
          throws BackingStoreException
  {
    if (hive != HKEY_CURRENT_USER && hive != HKEY_LOCAL_MACHINE) {
      throw new IllegalArgumentException("Invalid hive " + hive);
    }
 
    final Class clazz = Preferences.userRoot().getClass();
 
    try {
      final Method openKeyMethod = clazz.getDeclaredMethod("WindowsRegOpenKey",
              int.class, byte[].class, int.class);
      openKeyMethod.setAccessible(true);
 
      final Method closeKeyMethod = clazz.getDeclaredMethod("WindowsRegCloseKey",
              int.class);
      closeKeyMethod.setAccessible(true);
 
      final Method queryValueMethod = clazz.getDeclaredMethod("WindowsRegQueryValueEx",
              int.class, byte[].class);
      queryValueMethod.setAccessible(true);
 
      int[] result = (int[]) openKeyMethod.invoke(null, hive, stringToByteArray(keyName), KEY_READ);
      if (result[ERROR_CODE] != ERROR_SUCCESS) {
        if (result[ERROR_CODE] == ERROR_FILE_NOT_FOUND) {
          throw new BackingStoreException("Not Found error opening key " + keyName);
        }
        else {
          throw new BackingStoreException("Error " + result[ERROR_CODE] + " opening key " + keyName);
        }
      }
 
      int hKey = result[NATIVE_HANDLE];
 
      byte[] b = (byte[]) queryValueMethod.invoke(null, hKey, stringToByteArray(valueName));
      closeKeyMethod.invoke(null, hKey);
 
      if (b == null)
        return null;
      else
        return byteArrayToString(b);
    }
    catch (InvocationTargetException e) {
      throw new BackingStoreException(e.getCause());
    }
    catch (NoSuchMethodException e) {
      throw new BackingStoreException(e);
    }
    catch (IllegalAccessException e) {
      throw new BackingStoreException(e);
    }
  }
 
  /**
   * Returns this java string as a null-terminated byte array
   *
   * @param str The string to convert
   * @return The resulting null-terminated byte array
   */
  private static byte[] stringToByteArray(String str)
  {
    byte[] result = new byte[str.length() + 1];
    for (int i = 0; i < str.length(); i++) {
      result[i] = (byte) str.charAt(i);
    }
    result[str.length()] = 0;
    return result;
  }
 
  /**
   * Converts a null-terminated byte array to java string
   *
   * @param array The null-terminated byte array to convert
   * @return The resulting string
   */
  private static String byteArrayToString(byte[] array)
  {
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < array.length - 1; i++) {
      result.append((char) array[i]);
    }
    return result.toString();
  }
 
  @SuppressWarnings({"UseOfSystemOutOrSystemErr", "HardcodedFileSeparator"})
  private static void testKey(int hive, String keyName, String valueName)
  {
    String s;
 
    if (hive == HKEY_CURRENT_USER) System.out.print("HKCU\\");
    if (hive == HKEY_LOCAL_MACHINE) System.out.print("HKLM\\");
    System.out.println(keyName);
    System.out.println("  Reading: " + valueName);
 
    try {
      s = getKeySz(hive, keyName, valueName);
      System.out.println("    >>" + s + "<<");
    }
    catch (BackingStoreException e) {
      System.out.println("    !!" + e.getMessage());
    }
  }
 
  @SuppressWarnings({"HardcodedFileSeparator", "DuplicateStringLiteralInspection"})
  public static void main(String args[])
  {
    testKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam", "InstallPath");
    testKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam\\Apps\\15660", "");
    testKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam\\Apps\\22000", "");
    testKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam\\Apps\\22010", "");
  }
}

*™Google

Comments

I had been in a mesh when i

May 16, 2016 by imac23, 1 week 6 days ago
Comment: 1825

I had been in a mesh when I was using the iphone for the first time as the gift cards were way too costly i was trying to have some free iTunes cards as I was told by my friend that why we use gift cards when the codes are generated randomly at this website and also you can have this website for music and TV shows streaming.

I read through the code but

May 15, 2016 by Bill Nicolas, 2 weeks 10 hours ago
Comment: 1781

I read through the code but recognizing the algorithm behind it was not understood by me. You should have had got http://www.boomerangreview.com/ provide you a clear-cut explanation on the topic so the mainstream audience would have no problem understanding the complex code.

Thanks.

May 7, 2016 by khachlamat, 3 weeks 1 day ago
Comment: 1620

I'm planar by your table make

May 11, 2016 by alex12, 2 weeks 4 days ago
Comment: 1701

I'm planar by your table make up the superior production.visit site

Without entering the JNI code

May 2, 2016 by jhonson, 3 weeks 6 days ago
Comment: 1523

Without entering the JNI code implementing the windows registry is a very creative discovery made. What ever code has been given above is clear and i really wanted to make a try it with my essayontime projects. And i really hope with the best outcome.

Your article is much

April 18, 2016 by LucaKhloe, 5 weeks 6 days ago
Comment: 1165

Your article is much informative and solves my java problem but to make it more user-friendly, visit rushessay as they will help ease up the pressure with delinquent writing.

Thanks

April 11, 2016 by khachlamat, 6 weeks 6 days ago
Comment: 1018

On non-Windows platforms, or

April 13, 2016 by alex12, 6 weeks 4 days ago
Comment: 1068

On non-Windows platforms, or if the WindowsPreferences implementation changes, a BackingStoreException will be thrown.bathroom vanities Plantation

Your blogs and every other

April 13, 2016 by alex12, 6 weeks 4 days ago
Comment: 1051

Your blogs and every other content is so entertaining and useful It makes me come back again.
gospeltracts evangelism tracts

I don’t know what to say

March 13, 2016 by alex12, 11 weeks 5 hours ago
Comment: 475

I don’t know what to say except that I have enjoyed reading. Nice blog, I will keep visiting this blog very often.recuperacao de dados

I have not implemented the

March 17, 2016 by alex12, 10 weeks 3 days ago
Comment: 513

I have not implemented the write methods as I had no need for them, but they should be equally easy to do.limo

The afrika mangosu on his

March 15, 2016 by alex12, 10 weeks 5 days ago
Comment: 494

The afrika mangosu on his show not only as a weight loss aid, but as a perfect potent multivitamin that has benefits for both men and women.website hosting

Question

May 22, 2014 by nid69ita, 2 years 1 week ago
Comment: 103

Hi, I know it's an old project.
You know if exist some command like RegQueryVal accessible in Java like your system for reading everywhere in registry ?
I need to Enumerate some subkeys in registry.
Thank you, Igor Noro

Sorry for my English