Monday, April 6, 2009

Another Way To Call A Native Method: JNA

Three days ago there was an article titled "Calling a .NET Method from Java via JNI" in this blog. In that approach we had to do some native development in order to call a .NET method from Java side. We had...
  • ...created a java class with native declarations and we had compiled it
  • ...created header files with javah (so with JNI)
  • ...developed an implementation of header files, we used C++ and we called .NET methods (so our implementation was a wrapper for the target dll) and we compiled the DLL (which were going to be a bridege between Java and .NET) with Visual Studio
Then I heard that I could also achieve this with JNA (JNA stands for Java Native Access). JNA allows you to access native libaries and call methods in that library. You only need to define native methods in an interface. (You should already know the signatures of the methods you are going to use anyway.) Also there is a tool called jnaerator which generates those interfaces for you but it is so limited and not matured yet.

I was told that I even do not need to touch Visual Studio nor use JNI directly becouse JNA was invoking native codes directly. However later on I explored that this was where they were wrong. Becouse, if you want to call a method in a class (which is written for example in C++ or C#) and which is compiled to dll, you still need to write a wrapper in C and procude a DLL (Here is the recommendation, it is actually what we had done with JNI too). So JNA does not help in this case.

However if it was method like printf in msvcrt library, we might make a use of JNA. I am saying maybe becouse using JNA is much slower then JNI!

This excerpt is from JNA project site: A simple test calling a function like int testfunc(int) with JNA might take an order of magnitude (~10X) greater time than equivalent custom JNI (whether it actually does in the context of your application is a different question).

This is still why I would choose to go with JNI. I feel more safe and have more control when I use JNI. Also JNA lacks loading initiating/classes. (Please correct me if I am wrong, but if I am wrong then this time I will start to complain about lack of documentation/example). JNI has more documentation, and it is more standarized. Of course they are not competing technologies but for now I keep distance with JNA.

However, assume if you have a native method in abcLib with a signature int compute(), then you could:

  1. Download jna.jar (download comes with .zip extension but it is a jar infact, so rename .zip to .jar)
  2. Then wrote your interface like:
    package mytrial;
    import com.sun.jna.Library;
    public interface MyInterface  extends Library  {
    public int compute();
    }
    
    
  3. Then we can call native method easyly. Here is the code for calling our native method:

    package mytrial;
    
    import com.sun.jna.Native;
    public class Main {
    public static void main(String[] args) {
    MyInterface lib = (MyInterface) Native.loadLibrary("abcLib", MyInterface.class);
    lib.compute();
    }
    }
    
    

So if we summary, I do no recommend JNA if performance is essential for you. Or if you are going to call a method in a class written with in .NET or unmannaged C++.

However maybe I am wrong, here are the projects that are using jna.

3 comments:

  1. "Or if you are going to call a method in a class written with in .NET or unmannaged C++." So you basically saying to not use it at all?

    ReplyDelete
  2. You may consider using it if you are going to call a function from a standard C library (like printf) or a native call from windows api (like DefDlgProc).

    ReplyDelete