- JNA does not support mapping of c++ classes, so if you're using c++ library you will need a jni wrapper
- If you need a lot of memory copying. For example, you call one method which returns you a large byte buffer, you change something in it, then you need to call another method which uses this byte buffer. This would require you to copy this buffer from c to java, then copy it back from java to c. In this case jni will win in performance because you can keep and modify this buffer in c, without copying.
These are the problems I've encountered. Maybe there's more. But in general performance is not that different between jna and jni, so wherever you can use JNA, use it.
EDIT
This answer seems to be quite popular. So here are some additions:
- If you need to map C++ or COM, there is a library by Oliver Chafic, creator of JNAerator, called BridJ. It is still a young library, but it has many interesting features:
- Dynamic C / C++ / COM interop : call C++ methods, create C++ objects (and subclass C++ classes from Java!)
- Straightforward type mappings with good use of generics (including much nicer model for Pointers)
- Full JNAerator support
- works on Windows, Linux, MacOS X, Solaris, Android
- As for memory copying, I believe JNA supports direct ByteBuffers, so memory copying can be avoided.
So, I still believe that wherever possible, it is better to use JNA or BridJ, and revert to jni if performance is critical, because if you need to call native functions frequently, performance hit is noticeable.