Мне нужно приложение Java для управления реестром Windows. Для этого я написал некоторый нативный код C ++ и использовал его для вызова JNI.
По большей части это работает. Во время тестирования я не слышал ни об одной проблеме. Однако недавно у пользователя произошел сбой в коде C ++, который вызвал сбой JVM. Подробности ниже. У меня почти нет опыта работы с C ++, поэтому я думаю, что мне нужна помощь. Я думаю, что проблема связана с разрешениями, так как, когда приложение Java запускается от имени администратора, проблема исчезает. Проблема в том, что не все наши пользователи будут иметь права администратора на своих машинах.
hs_err_pid log info:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000076859083, pid=5316, tid=3116
#
# JRE version: 6.0_20-b02
# Java VM: Java HotSpot(TM) 64-Bit Server VM (16.3-b01 mixed mode windows-amd64 )
# Problematic frame:
# C [kernel32.dll+0x9083]
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Stack: [0x0000000013010000,0x0000000013110000], sp=0x000000001310f2d0, free space=3fc0000000000000000k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [kernel32.dll+0x9083]
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j my.package.WinRegUtils.SetKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z+0
j java.lang.Thread.run()V+11
v ~StubRoutines::call_stub
Вот родной код / рассматриваемый метод
JNIEXPORT jboolean JNICALL Java_my_package_WinRegUtils_SetKeyValue
(JNIEnv* env, jclass clazz, jstring jRootKey, jstring jKey, jstring jValueName, jstring jValueData, jstring jDataType)
{
bool success = false;
WCHAR* key_w;
WCHAR* valueName_w;
WCHAR* valueData_w;
WCHAR* dataType_w;
HKEY hKey;
const char* rootKey = env->GetStringUTFChars(jRootKey, false);
const char* key = env->GetStringUTFChars(jKey, false);
convertString(key, &key_w);
const char* valueName = env->GetStringUTFChars(jValueName, false);
convertString(valueName, &valueName_w);
const char* valueData = env->GetStringUTFChars(jValueData, false);
convertString(valueData, &valueData_w);
const char* dataType = env->GetStringUTFChars(jDataType, false);
convertString(dataType, &dataType_w);
HKEY root = GetRootHKEY(rootKey);
if (RegOpenKeyEx(root, key_w, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
{
DWORD dwType;
BYTE* data;
DWORD length;
if (strcmp("REG_SZ", dataType) == 0)
{
dwType = REG_SZ;
data = (BYTE*)valueData_w;
length = wcslen(valueData_w) * sizeof(DWORD);
}
else if (strcmp("REG_DWORD", dataType) == 0)
{
dwType = REG_DWORD;
const DWORD intData = atoi(valueData);
data = (BYTE*)&intData;
length = sizeof(DWORD);
}
if (RegSetValueEx(hKey, valueName_w, 0, dwType, data, length) == ERROR_SUCCESS)
{
success = true;
RegCloseKey(hKey);
}
}
env->ReleaseStringUTFChars(jRootKey, rootKey);
env->ReleaseStringUTFChars(jKey, key);
env->ReleaseStringUTFChars(jValueName, valueName);
env->ReleaseStringUTFChars(jValueData, valueData);
env->ReleaseStringUTFChars(jDataType, dataType);
delete[] key_w, valueName_w, valueData_w, dataType_w;
return success;
}