EXCEPTION_ACCESS_VIOLATION (0xc0000005)来自JNI的JVM?

3

我使用JNI在vc++中编写了一些本地方法,供java调用。我的三个方法中,有两个完全正常没有任何问题。然而,当我在运行时调用最后一个方法时,会出现以下错误信息:

# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x61e06550, pid=3408, tid=4796
#
# JRE version: 7.0-b147
# Java VM: Java HotSpot(TM) Client VM (21.0-b17 mixed mode, sharing windows-x86 )
# Problematic frame:
# V  [jvm.dll+0xa6550]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows

以下是我的本地方法代码(使用vc ++):

JNIEXPORT jcharArray JNICALL Java_jniusb_Main_receiveData (JNIEnv *env, jclass, jchar dataIndex)
{
    DWORD BytesWritten = 0;
    DWORD BytesRead = 0;
    unsigned char OutputPacketBuffer[65];   
    unsigned char InputPacketBuffer[65];    

    static jcharArray ReturnPacketBuffer;
    jchar temp[65];

    //send 'receive data' command to the firmware (OutputPacketBuffer[1])
    WriteFile(WriteHandle, &OutputPacketBuffer, 65, &BytesWritten, 0);
        //retrieve data from firmware
    ReadFile(ReadHandle, &InputPacketBuffer, 65, &BytesRead, 0);        

        for(int i=0;i<64;i++) 
    {
        temp[i] = jchar(InputPacketBuffer[i+1]);
    }

    (*env).SetCharArrayRegion(ReturnPacketBuffer, 0, 64, temp);
    return ReturnPacketBuffer;
}

我的Java代码看起来像这样(当然是缩短版):

public static native char[] receiveData(char dataIndex);

public static void main(String[] args) {
    char vid = 0x4d8;
    char pid = 0x3f;

    //check if read/write handles were retrieved 
    if(connectHid(vid, pid) == true)
    {
        System.out.println("connected!!!");
    }
    else
    {
        System.out.println("not connected...");
    }


    char[] test = new char[64];
    char[] receivetest = new char[64];

    char length = 0x03;
    char dataIndex = 0x81;

    test[0] = 0x80;
    test[1] = 0x80;
    sendData(test, length);
    receivetest = receiveData(dataIndex);

就像我之前说过的那样,其他方法(即connect和senddata)运行良好,但我从receiveData方法中获得错误。经过一些调试,我发现当我注释掉以下行时,错误会消失:

(*env).SetCharArrayRegion(ReturnPacketBuffer, 0, 64, temp);

在我的本地代码中(当然,在这种情况下数据永远不会被返回...)。我在这里做错了什么?


for (int i=0; i<65; i++) - Usman Saleem
3个回答

2
你是不是忘了像这样的东西 ReturnPacketBuffer = (*env)->NewCharArray(env, 64);

我以前从未使用过JNI,所以我不知道这个,但它似乎解决了所有问题,谢谢! - Ben

2
异常代码指未初始化的内存访问,提示:请查找越界索引。

1
for(int i=0;i<64;i++) 
{
    temp[i] = jchar(InputPacketBuffer[i+1]);
}

temp可以容纳65个jchar类型的元素。它们最初保存一些垃圾值。通过上述循环,你尝试填充从063个元素。最后一个元素未被填充,并保留了最初的垃圾值。

(*env).SetCharArrayRegion(ReturnPacketBuffer, 0, 64, temp);

很可能,上述语句在temp的第64个索引处的值上运行,由于其中包含垃圾数据而导致失败。尝试使用小于64的索引,它应该可以正常工作。或者通过将for循环迭代增加一次并填充第64个索引处的有效值来解决问题。


我认为64不代表索引,而是长度。因此,这应该设置64个字符。 - Ben van Gompel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接