用Java11读取Windows注册表

用Java11读取Windows注册表,java,module,registry,Java,Module,Registry,我正在将一个应用程序从Java8转换为Java11,这意味着我必须处理模块化的JRE。读取Windows注册表项的例程失败,出现不可访问的ObjectException;信息是 java.lang.reflect.InaccessibleObjectException:无法使私有长java.util.prefs.WindowsPreferences.openKey(字节[],int,int)可访问:模块java.prefs不会“打开java.util.prefs”到模块myModule。 mod

我正在将一个应用程序从Java8转换为Java11,这意味着我必须处理模块化的JRE。读取Windows注册表项的例程失败,出现不可访问的ObjectException;信息是 java.lang.reflect.InaccessibleObjectException:无法使私有长java.util.prefs.WindowsPreferences.openKey(字节[],int,int)可访问:模块java.prefs不会“打开java.util.prefs”到模块myModule。 module-info.java文件包含语句“requires java.prefs;”。 在下面的方法中,行“openKey.setAccessible(true);”引发异常。是否应该向module-info.java文件中添加其他语句

    public static String getRegistryValue(String key, String name, Logger log) 
{
    String vals = null;
    //Retrieve a reference to the root of the system preferences tree
    final Preferences systemRoot = Preferences.systemRoot();
    final Class <?> clz = systemRoot.getClass();

    try {
        Class <?>[] params1 = {byte[].class, int.class, int.class};
        final Method openKey = clz.getDeclaredMethod(
                "openKey", params1);
        openKey.setAccessible(true);

        Class <?>[] params2 = {int.class};
        final Method closeKey = clz.getDeclaredMethod(
                "closeKey", params2);
        closeKey.setAccessible(true);

        final Method winRegQueryValue = clz.getDeclaredMethod(
                                            "WindowsRegQueryValueEx", 
                                            int.class,
                                            byte[].class); 
        winRegQueryValue.setAccessible(true);

        int hKey = (Integer) openKey.invoke(systemRoot, 
                                            toByteEncodedString(key), 
                                            KEY_READ, 
                                            KEY_READ);
        byte[] valb = (byte[]) winRegQueryValue.invoke(systemRoot, hKey,
                  toByteEncodedString(name));
        vals = (valb != null ? new String(valb).trim() : null);
        closeKey.invoke(Preferences.systemRoot(), hKey);              
    }
    catch (Exception e) {
        log.log(Level.SEVERE, "getRegistryValue failed for " +
                key + "\\" + name);
        JFrame frame =  new JFrame();
        JOptionPane.showMessageDialog(frame, "Event viewer cannot be opened.",
                "error", JOptionPane.ERROR_MESSAGE);
    }
    return vals;
}
public静态字符串getRegistryValue(字符串键、字符串名称、记录器日志)
{
字符串VAL=null;
//检索对系统首选项树根的引用
final Preferences systemRoot=Preferences.systemRoot();
最终类clz=systemRoot.getClass();
试一试{
Class[]params1={byte[].Class,int.Class,int.Class};
最终方法openKey=clz.getDeclaredMethod(
“openKey”,参数1);
openKey.setAccessible(true);
类[]params2={int.Class};
最终方法closeKey=clz.getDeclaredMethod(
“关闭键”,参数2);
closeKey.setAccessible(true);
最终方法winRegQueryValue=clz.getDeclaredMethod(
“WindowsRegQueryValueEx”,
国际级,
字节[]。类);
winRegQueryValue.setAccessible(true);
int hKey=(整数)openKey.invoke(systemRoot,
toByteEncodedString(键),
钥匙读到了,
键(读取);
字节[]值=(字节[])winRegQueryValue.invoke(systemRoot,hKey,
toByteEncodedString(名称));
vals=(valb!=null?新字符串(valb).trim():null);
调用(Preferences.systemRoot(),hKey);
}
捕获(例外e){
log.log(Level.severy,“getRegistryValue失败”+
键+“\\”+名称);
JFrame=新JFrame();
JOptionPane.showMessageDialog(框架,“无法打开事件查看器”,
“错误”,作业窗格。错误消息);
}
返回VAL;
}

使用VM选项运行应用程序

--add-opens java.prefs/java.util.prefs=<your-module-name>
--add打开java.prefs/java.util.prefs=
其中,模块名称是需要对java.util.prefs.WindowsPreferences进行反射访问的模块的名称

使用--add以反射方式访问内部API打开

java选项--add打开$module/$package=$reflectingmodule可以 用于打开$module的$package进行深入反思 $reflectingmodule。因此,$reflectingmodule中的代码可以进行反射 访问$package中的所有类型和成员,但其他模块无法访问