Native code, JNI

Recently I posted on how to incorporate native code in OSGi bundles. Well, some questions surface now and then, particularly "then" nowadays (thanks to the recent posting), regarding the actual native code production.

To start with there is a good tutorial on the subject provided by Sun. Secondly, and probably a bit harder to obtain, is a very good book on the subject: Essential JNI - Java Native Interface, by Rob Gordon (ISBN 0-13-679895-0). It seems to have gone out of print. That is a pity as it is considered one of the best books on the subject. It explains all parts of JNI well, and it has very good examples.

But, how do you get about dealing with native code? What pitfalls are there? Rules of Thumb? Here is a check list for you, hope it is of help when you are about to select the path ahead:

  1. When do I need to employ JNI? Answer: Never!
    Well, in 99,9 % of the cases you are better off not using JNI. I.e. native code does not always execute faster - running Java code in the HotSpot JVM can actually be equally as fast or sometimes even faster! Further; check to see if there is another solution, open source maybe, that does what you need. They might have fixed the interfacing chore for you...

  2. Ok, but you've got some legacy stuff on your hands. Now do you need JNI? Yes, maybe, but there might be other techniques you can employ. Have you checked pipes, shared memory or sockets? Please keep in mind that loading a shared library into a process space might crash the process if some piece of code in the library crashes. You are outside the Java Sandbox, but still within the same process space. The other techniques mentioned have the library execute in a separate process, then you have a problem of checking liveliness instead.

  3. You are about to interface and use COM-components or ActiveX Controls on Windows. Required to learn everything about COM, DCOM, ActiveX, etc? No, not really. Ok, knowledge is no burden, as every abstraction leaks you should at least learn the basics on COM. For the interfacing problem, as mentioned before, somebody else has already taken care of the JNI part you in this case: e.g. the COM - Java Bridge JACOB, and others...

  4. You are still here? Ok, maybe JNI is the solution for you. Are there any pitfalls? Oh yes! There are plenty, in most cases we are talking about writing code in C or C++ here. As some of you already are aware of, it is much easier to create code that will malfunction in C/C++ than Java! Do not get me wrong here; C and C++ are perfectly ok languages too, it just that you have to take more aspects into consideration and be careful of pointers, casts, void*, etc.
    Then, there is loading of the library, on Linux/Unix check your LD_LIBRARY_PATH, om Win32 the PATH variable. That also goes for those libraries your library depends on.

  5. Other considerations:

    • Strings - in Java a String instance is an object, needs to be converted on the native side using the special GetStringUTFChars function. It is released using the ReleaseStringUTFChars whendone with.

    • Exceptions - if calling Java code from the native side, under some circumsances you need to check for possible exceptions thrown, or you might run into trouble.

    • If you are into C++, using the bridge design pattern can be a powerful approach; Java classes are mirrored on the native side implementation in the C++ classes. Have them comminucate through JNI.

Despite what I say (write) in the bullets above I am an advocate of JNI. Every Java assignment I've had has involved some work using JNI - there has been no exceptions so far. JNI is a powerful technology and correctly used it will leverage your project.

1 comment:

saujee said...

hey, do you have a example or guide to use JNI with C++ in Eclipse/Linux platform.