EXCEPTION_ACCESS_VIOLATION (0xc0000005) JVM от JNI? - PullRequest
3 голосов
/ 07 октября 2011

Я написал несколько нативных методов в vc ++ с JNI для доступа из 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);

в моем родном коде (конечно, в этом случае данные никогда не возвращаются ...). Что я здесь не так делаю?

Ответы [ 3 ]

2 голосов
/ 07 октября 2011

Не упускаете ли вы что-то вроде ReturnPacketBuffer = (*env)->NewCharArray(env, 64);

1 голос
/ 07 октября 2011
for(int i=0;i<64;i++) 
{
    temp[i] = jchar(InputPacketBuffer[i+1]);
}

temp может содержать 65 элементов типа jchar. Они изначально содержат некоторые значения мусора. С помощью вышеуказанного цикла вы пытаетесь заполнить элементы от 0 до 63 . Последний элемент остается незаполненным и остается со значением мусора, которое он имел изначально.

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

Возможно, вышеприведенный оператор работает со значением в 64-м индексе temp и не выполняется из-за мусора в нем. Попробуйте дать индекс меньше 64, все работает, ИМО. Или заполните 64-й индекс также допустимым значением, увеличивая итерацию цикла for до другой.

1 голос
/ 07 октября 2011

Код исключения предназначен для доступа к неинициализированной памяти, в качестве подсказки ищите индексирование за пределами.

...