如何在JNI中通过引用?

时间:2016-06-16 20:18:52

标签: c reference java-native-interface buffer

好的,我之前已经问过这个问题,但我认为答案在这方面有所不同。所以基本上我有一个C库,其中包含函数seal和unseal,如下所示:

JNIEXPORT jint JNICALL Java_JavaTest_securesdk_1seal_1data
(JNIEnv *env, jobject obj, jlong handle, jbyteArray data, jint size)
{
    const char *cData = (*env)->GetByteArrayElements(env, data NULL);
    jint token = securesdk_seal_data(handle, cData, size);
    (*env)->ReleaseByteArrayElements(env, data, cData, JNI_ABORT);
    return token;
}

JNIEXPORT jint JNICALL Java_JavaTest_securesdk_1unseal_1data
(JNIEnv *env, jobject obj, jlong handle, jint token, jbyteArray data, jint size)
{
    const char *buffer = (*env)->GetByteArrayElements(env, data NULL);
    jsize length = (*env)->GetArrayLength(env,data);
    jlong address = securesdk_unseal_data(handle, token, buffer, size);
    for(int i=0; i<length; i++){
        printf("%i\n", buffer[i])
    }
    (*env)->ReleaseByteArrayElements(env, data, buffer, JNI_ABORT);
    return address;
}

基本上,seal函数接受Java端的字节数组并将其存储在闪存中(不用担心它是如何工作的)并返回一个令牌。 unseal函数接受一个空字节数组缓冲区和令牌,并用数据填充空缓冲区。现在这里是java代码及其输出内容。

class JavaTest{
    public native int securesdk_seal_data(long handle, byte[] data, int size);
    public native int securesdk_unseal_data(long handle, int token, byte[] data, int size);

    JavaTest test = new JavaTest();
    String data = "hello";
    byte[] cmdbuf = data.getBytes();
    int token = test.securesdk_seal_data(sdk, cmdbuf, cmdbuf.length);
    byte[] emptybuf = new byte[10];
    long returnData = test.securesdk_unseal_data(sdk, token, emptybuf, emptybuf.lenth);

    for(int i=0; i<emptybuf.length; i++){
        System.out.print(emptybuf[i]);
    }
}

因此,当我运行java代码时,它会从C代码中的printf语句中打印出“hello”的字节。当我传入空缓冲区时,它会填充我最初密封的数据。这是正确的。但是当我在Java中调用unseal函数后尝试打印填充的缓冲区时,它仍然返回空缓冲区。如何在调用C函数后从内存中获取缓冲区?这可能吗?当我从Java打印emptybuf时,我希望打印出“hello”的字节,而不仅仅是来自C.谢谢。

1 个答案:

答案 0 :(得分:0)

开封中,而不是JNI_ABORT传递0:

(*env)->ReleaseByteArrayElements(env, data, buffer, 0);