5

I have an Android project (targeting Android 1.6 and up) which includes native code written in C/C++, accessed via NDK. I'm wondering what the most efficient way is to pass an array of bytes from Java through NDK to my JNI glue layer. My concern is around whether or not NDK for Android will copy the array of bytes, or just give me a direct reference. I need read-only access to the bytes at the C++ level, so any copying behind the scenes would be a waste of time from my perspective.

It's easy to find info about this on the web, but I'm not sure what is the most pertinent info. Examples:

Get the pointer of a Java ByteBuffer though JNI

http://www.milk.com/kodebase/dalvik-docs-mirror/docs/jni-tips.html

http://elliotth.blogspot.com/2007/03/optimizing-jni-array-access.html

So does anyone know what is the best (most efficient, least copying) way to do this in the current NDK? GetByteArrayRegion? GetByteArrayElements? Something else?

Community
  • 1
  • 1
occulus
  • 16,959
  • 6
  • 53
  • 76

1 Answers1

6

According to the documentation, GetDirectBufferAddress will give you the reference without copying the array.

However, to call this function you need to allocate a direct buffer with ByteBuffer.allocateDirect() instead of a simple byte array. It has a counterpart as explained here :

A direct byte buffer may be created by invoking the allocateDirect factory method of this class. The buffers returned by this method typically have somewhat higher allocation and deallocation costs than non-direct buffers. The contents of direct buffers may reside outside of the normal garbage-collected heap, and so their impact upon the memory footprint of an application might not be obvious. It is therefore recommended that direct buffers be allocated primarily for large, long-lived buffers that are subject to the underlying system's native I/O operations. In general it is best to allocate direct buffers only when they yield a measureable gain in program performance.

Community
  • 1
  • 1
Dalmas
  • 26,409
  • 9
  • 67
  • 80
  • Is there any similar efficient API for doing the opposite? - passing `unsigned char*` from native layer to Java layer as `byte[]` or `byteBuffer`? – Kaidul Oct 22 '15 at 09:14
  • Both direct ByteBuffer and byte[] can be used for read/write from/to native side. You can use C's memcopy function to read/copy, once you have called env->GetDirectBufferAddress(buffer) or env->GetArrayElements(array,...). BUT direct ByteBuffer is much faster, don't play copies, its safer, etc, etc – Alex Byrth Apr 26 '16 at 14:02