Well, it seems Ron beat me to the punch to blog about this – but allow me to promote the recently published developerWorks article that I had a hand in bringing to life: Best practices for using the Java Native Interface
Here is the summary:
The Java™ Native Interface (JNI) is a standard Java API that enables Java code to integrate with code written in other programming languages. JNI can be a key element in your toolkit if you want to leverage existing code assets — for example, in a service-oriented architecture (SOA) or a cloud-based system. But when used without due care, JNI can quickly lead to poorly performing and unstable applications. This article identifies the top 10 JNI programming pitfalls, provides best practices for avoiding them, and introduces the tools available for implementing these practices.
Many kudos to Michael Dawson for his wordsmithing and persistence to make this article happen, he really deserves the lion’s share of the credit.
Ron calls out his favorite pitfall as using the wrong JNIEnv. I’ll pick the one that makes me laugh because it is sad but true: Choosing the wrong boundary between native and Java code – believe it or not there was a real world example that motivated the sample code. The customer had decided to go for a “pure java” solution for their embedded application, so the minimal amount of native code was written – two functions that could read or write individual bits (not bytes). While the example is outlandish, many times the integration of legacy code via JNI is done without thinking of the cost of the boundary.
Let’s discuss the picking the right side of the JNI boundary for a minute. The NIO implementation is a good example of trying to fix file performance by keeping the data on the “right” side of the JNI boundary. While NIO provides other functions allowing for tighter OS integration, one key performance win is due to the file data is kept in native buffers. If you’re trying to get the data into java objects to be manipulated, you are likely defeating the performance win of NIO by forcing all that file data across the JNI boundary. Where NIO will excel is needing to pull a bunch of data from a file and put it in another file – if you don’t need to hoist that data up into the java object space, you’ll get close to pure native performance.
Please check out the article, or at least bookmark it and send it to people who write JNI code. Maybe we’ll see fewer false JVM bugs that turn out to be JNI related problems.