如何在 JNI 中调用 String.getBytes()?我想在 JNI 中获取字节数组,但 CallByteMethod 只是 returns jbyte 而不是 jbytearray

How to I call String.getBytes() in JNI? I want to get byte array in JNI but the CallByteMethod just returns jbyte and not the jbytearray

我正在尝试调用 String.getBytes() 方法从字符串对象获取 JNI 中的字节数组。 JNI 有 CallByteMethodCallByteMethodVCallByteMethodA 方法,其中 return 是 jbyte,但它没有 return 一个 java 字节数组的方法。

我试过调用 CallByteMethod 方法,但出现错误

JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0xd5ec7fe1

我尝试的其他代码是使用像这样的 jbytearray 转换

jbyteArray keyBytes = (jbyteArray)(*env)->CallByteMethod(env, stringValue, getBytesMId);

因为 IDE 显示警告

Taking pointer from integer without a cast.

但后来我收到一个不同的错误

JNI DETECTED ERROR IN APPLICATION: the return type of CallByteMethod does not match byte[] java.lang.String.getBytes()

下面是我的代码:

JNIEXPORT jstring JNICALL
Java_net_jni_test_MainActivity_callTest(JNIEnv *env, jobject instance) {

    jstring stringValue = "test";

    jclass stringClass = (*env)->FindClass(env, "java/lang/String");
    jmethodID getBytesMId = (*env)->GetMethodID(env, stringClass, "getBytes", "()[B");

    jbyteArray keyBytes = (*env)->CallByteMethod(env, stringValue, getBytesMId);

    return (*env)->NewStringUTF(env, "1111");
}

从您的代码中发现一些错误:

  1. 下一行是错误的:

    jstring stringValue = "test";
    

    它应该如下所示:

    jstring stringValue = (*env)->NewStringUTF(env, "test");
    
  2. CallObjectMethod得到jbyteArray,记得把return类型转换成jbyteArray。见下文:

    jbyteArray keyBytes = (jbyteArray)(*env)->CallObjectMethod(env, stringValue, getBytesMId);
    
  3. 下面是显示预期结果的屏幕截图。

完整来源:

JNIEXPORT jstring JNICALL
Java_net_jni_test_MainActivity_callTest(JNIEnv *env, jobject instance) {
    jstring stringValue = (*env)->NewStringUTF(env, "test");

    jclass stringClass = (*env)->FindClass(env, "java/lang/String");
    jmethodID getBytesMId = (*env)->GetMethodID(env, stringClass, "getBytes", "()[B");

    jbyteArray keyBytes = (jbyteArray)(*env)->CallObjectMethod(env, stringValue, getBytesMId);

    // determine the needed length and allocate a buffer for it
    jsize num_bytes = (*env)->GetArrayLength(env, keyBytes);


    // obtain the array elements
    jbyte* elements = (*env)->GetByteArrayElements(env, keyBytes, NULL);
    if (!elements) {
        // handle JNI error ...
    }

    for(int i = 0; i < num_bytes; i++) {
        char ch = elements[i];
        ALOGI("arrayLength: %c", ch);
    }

    // Do not forget to release the element array provided by JNI:
    (*env)->ReleaseByteArrayElements(env, keyBytes, elements, JNI_ABORT);
}

请注意C++ JNI和C JNI的区别。例如。 C 风格的 JNI 有以下方法约定:

jmethodID getBytesMId = (*env)->GetMethodID(env, stringClass, "getBytes", "()[B");

但 C++ 如下所示:

jmethodID getBytesMId = env->GetMethodID(stringClass, "getBytes", "()[B");