JNI在JVM外部崩溃 - EXCEPTION_ACCESS_VIOLATION

时间:2012-03-29 16:10:27

标签: java-native-interface

我需要一个Java应用程序来操作Windows注册表。为此,我编写了一些本机C ++代码并使用JNI来调用它。

大多数情况下都有效。在测试期间,我没有听说过一个问题。但是,最近用户遇到了导致JVM崩溃的C ++代码崩溃。详情如下。我几乎没有C ++经验,所以我认为这是我需要帮助的地方。我认为这个问题与权限有关,因为当Java应用程序以管理员身份运行时,问题就会消失。问题在于,并非所有用户都拥有自己计算机的管理员权限。

hs_err_pid日志信息:

#
# 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;
}

1 个答案:

答案 0 :(得分:0)

要调试,请添加一些

printf("debug xxx");
fflush(stdout);

in

Java_my_package_WinRegUtils_SetKeyValue()

隔离失败的线路。