Я нахожусь в процессе перехода с Java 7 (yipes) на Java 11 для веб-приложения, но у меня возникают трудности при переносе некоторого кода из-за недопустимых отражающих предупреждений о доступе (это не мешает работе, но должнона самом деле они когда-либо реализуют свои угрозы для принудительного применения в будущем обновлении JDK, я хочу, чтобы мой код был готов).
Я пытаюсь вызвать методы реестра из класса WindowsPreferences (который является закрытым классом впакет java.util.prefs, поставляемый с JDK 11.0.2).
Ранее у меня был код, который инициализировал бы методы в конструкторе моего служебного класса, например:
private static Preferences userRoot = Preferences.userRoot();
private static Class<? extends Preferences> userClass = userRoot.getClass();
private static Method regOpenKey = null;
...
static {
try {
regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey", new Class[] {int.class, byte[].class, int.class});
regOpenKey.setAccessible(true);
...
}
}
Я могзатем вызовите их позже так:
int[] handles = (int[]) regOpenKey.invoke(preferences, new Object[] {
new Integer(hive), toCstr(keyName), new Integer(KEY_READ | wow64) });
Это очень хорошо работало для Java 7, но в Java 11 мне пришлось переоборудовать некоторые вещи.
Теперь у меня есть:
private static Preferences userRoot = Preferences.userRoot();
private static Class<? extends Preferences> userClass = userRoot.getClass();
private static Method regOpenKey = null;
...
static {
try {
userRegOpenKey = userClass.getDeclaredMethod("openKey", byte[].class, int.class, int.class);
userRegOpenKey.setAccessible(true);
...
}
}
и
long handle = (long) userRegOpenKey.invoke(preferences, toCstr(keyName), hive, wow64));
Это работает достаточно хорошо, и я могу отлично читать из реестра, но каждый раз, когда я звоню .setAccessible(true)
на Method
из частного класса, Я получаю
ПРЕДУПРЕЖДЕНИЕ: Произошла недопустимая операция отражающего доступа
ПРЕДУПРЕЖДЕНИЕ: незаконный отражающий доступ com.admin.utils.RegistryManager (file: // WebRoot / WEB-INF / classes /) методу java.util.prefs.WindowsPreferences.closeKey (long)
ПРЕДУПРЕЖДЕНИЕ: пожалуйста, рассмотрите возможность сообщить об этом сопровождающим com.admin.utils.RegistryManager
ПРЕДУПРЕЖДЕНИЕ: используйте --illegal-access = warn, чтобы включитьпредупреждения о дальнейших незаконных операциях доступа с отражением
ПРЕДУПРЕЖДЕНИЕ. Все будущие операции доступа будут запрещены в следующем выпуске
Затем я попытался использовать Lookup
, чтобы получить MethodHandle
s, используя unreflect
, нопроблема сохраняется, поскольку класс является закрытым (это для другого метода, но это тот же базовый принцип):
Lookup lookup = MethodHandles.lookup();
Method systemRegCloseKeyDeclaredMethod = systemClass.getDeclaredMethod("closeKey", long.class);
systemRegCloseKeyDeclaredMethod.setAccessible(true);
systemRegCloseKey = lookup.unreflect(systemRegCloseKeyDeclaredMethod);
Я все равно получаю предупреждение о systemRegCloseKeyDeclaredMethod.setAccessible(true);
, но если я закомментирую это, тоЯ получаю исключение во время выполнения:
java.lang.IllegalAccessException: класс не является открытым: java.util.prefs.WindowsPreferences.closeKey [Ljava.lang.Object; @ 4c6e276e / invokeVirtual, из com.admin.utils.RegistryManager (неназванный модуль @ 6ee52dcd)
Что мне следует делать, чтобы правильно отразить закрытый класс (или это на самом деле то, что я не должен делать)