Returning null from native methods using JNI
c++, java, java-native-interface
Solution
This is an old question but I had it too a minute ago...
You say in your question:
return 0; // Does NOT work - doesn't crash, just slows everything down horrible.
I just gave a try actually, with a `jintArray` as this is what my code has to allocate and return, unless an error happens (defined by some criteria not related to this topic) in which case it has to return a null result.
It happens that returning `NULL` (defined as `((void*)0)`) works perfectly and is interpreted as `null` when back to the Java side. I didn't notice any degradation of the performances. And unless I missed anything returning `0` with no `void *` cast would not change anything to this.
So I don't think this was the cause of the slowdown you encountered. `NULL` looks just fine to return `null`.
EDIT:
I do confirm, the return value has nothing to do with performances. I just tested a same code returning a null value on a side, and its counterpart returning an object (a `jintArray`) on the other. Performances are similar for `NULL`, a `jintArray` of size 0, and a random `jintArray` of a few KBs allocated statically.
I also tried changing the value of a caller class's field, and returing void, with roughly the same performances. A very very little bit slower, probably due to the reflection code needed to catch that field and set it.
All these tests were made under Android, not under Java standalones - maybe this is why? (see comments):
- An API 17 x86 emulator running under HAXM
- An API 19 one, running under the same conditions
- Two API 19 physical devices - an Asus tablet and a Galaxy 5 - running under Dalvik.
Problem
I have some native code which returns a jbyteArray (so byte[] on the Java side) and I want to return null. However, I run into problems if I simply return 0 in place of the jbyteArray. Some more information: The main logic is in Java, the native method is used to encode some data into a byte stream. don;t ask.. it has to be done like this. Recently, the native code had to be changed a bit and now it runs horribly horrible slow. After some experimentation, which included commenting out all code in the native method before the return, it turns out that returning 0 causes the slowdown. When returning an actual jbyteArray, everything is fine. Method signatures for my code: On the C++ side: ``` extern "C" JNIEXPORT jbyteArray JNICALL Java_com_xxx_recode (JNIEnv* env, jclass java_this, jbyteArray origBytes, jobject message) ``` On the Java side: ``` private static native byte[] recode(byte[] origBytes, Message message); ``` The native code looks something like this: ``` jbyteArray javaArray; if (error != ERROR) { // convert to jbyteArray javaArray = env->NewByteArray((jsize) message.size); env->SetByteArrayRegion(java_array, 0, message.size, reinterpret_cast<jbyte*>(message.buffer())); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); error = ERROR; } } if (error == ERROR) { return 0; // Does NOT work - doesn't crash, just slows everything down horrible. } else { return javaArray; // Works perfectly. } ``` Does anyone know of any reasons that this could happen? Is it valid to return NULL from a native method in place of a jbyteArray, or is there another procedure to return null back to Java. Unfortunately, I had no luck on Google. Thanks! EDIT: Added additional information.