Issue
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");
}
Solution
Just spot some errors from your code:
Below line is wrong:
jstring stringValue = "test";
And it should be like below:
jstring stringValue = (*env)->NewStringUTF(env, "test");
Use
CallObjectMethod
to get thejbyteArray
, remember to cast the return type tojbyteArray
. See below:jbyteArray keyBytes = (jbyteArray)(*env)->CallObjectMethod(env, stringValue, getBytesMId);
Below is a screenshot showing the expected result.
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");
Answered By - shizhen
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.