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

Sam :

I am trying to call String.getBytes() method to get byte array in JNI from a string object. The JNI has methods CallByteMethod, CallByteMethodV and CallByteMethodA which returns jbyte but it has no methods to return a java byte array.

I have tried calling CallByteMethod method, but I get an error

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

The other code I tried was using a cast of jbytearray like this

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

since the IDE showed a warning

Taking pointer from integer without a cast.

but then I get a different error that says

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

Below is my code:

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");
}
shizhen :

Just spot some errors from your code:

  1. Below line is wrong:

    jstring stringValue = "test";
    

    And it should be like below:

    jstring stringValue = (*env)->NewStringUTF(env, "test");
    
  2. Use CallObjectMethod to get the jbyteArray, remember to cast the return type to jbyteArray. See below:

    jbyteArray keyBytes = (jbyteArray)(*env)->CallObjectMethod(env, stringValue, getBytesMId);
    
  3. Below is a screenshot showing the expected result.

    enter image description here

For full source:

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);
}

Please note the difference of C++ JNI and C JNI. E.g. C style JNI have below method convention:

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

But C++ is like below:

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=153081&siteId=1