JVM-Crash 在 JNI 中调用 ReleaseStringUTFChars,仅在 Windows 7 上,Win

JVM-Crash in JNI call ReleaseStringUTFChars, only on Windows 7, Windows XP fine

本文关键字:仅在 Windows Win ReleaseStringUTFChars JNI 调用 JVM-Crash      更新时间:2023-10-16

以下是通过JNI从Java JVM调用C++代码的摘录:

(JNIEnv *pJniEnv, jobject, jstring pDllName)
    {
           string dllName(pJniEnv->GetStringUTFChars(pDllName, NULL));
           // stuff happens here like
           HINSTANCE loadedDll = LoadLibrary(dllName.c_str());
           pJniEnv->ReleaseStringUTFChars(pDllName, dllName.c_str());
           return ...;
    }

这在Windows XP中有效,但在Windows 7中崩溃,并出现访问冲突异常,在行中

 pJniEnv->ReleaseStringUTFChars(pDllName, dllName.c_str());

错误消息是:

java 中的首次机会0x77355F29异常 (ntdll.dll) .exe: 0xC0000005:访问冲突读取位置0x002B0D52。

我会感谢任何线索。

JRE 版本:6.0_27-b07,Java VM:Java HotSpot(TM) Client VM (20.2-b06 mixed mode windows-x86),C++ 代码是使用 Visual Studio 2010 构建的。

GetStringUTFChars()的文档指出:

返回指向字符串的 UTF-8 字符数组的指针。 此数组在 ReleaseStringUTFChars 发布之前有效。

ReleaseStringUTFChars() 状态的文档(其中 string 是第一个参数,utf 是第二个参数):

通知虚拟机实现本机代码没有 更长需要访问本机字符串 UTF。utf 参数 是使用 GetStringUTFChars 从字符串派生的指针。

在发布的代码中,dllName.c_str()作为第二个参数传递给ReleaseStringUTFChars()这是不正确的c_str()因为它归dllName所有(std::string的构造函数会复制其参数),而不是从pDllName派生出来的。这在一个平台上而不是另一个平台上工作的事实表明了未定义的行为。

要更正:

const jbyte* pDllName_string = pJniEnv->GetStringUTFChars(pDllName, NULL);
std::string dllName(pDllName_string);
pJniEnv->ReleaseStringUTFChars(pDllName, pDllName_string);
/* Use 'dllName' */