Java Native Access: What, How, and Performance Comparison

While trying the libvirt Java binding, I came to know Java Native Access (JNA) which is a great alternative to Java Native Interface (JNI). As it’s said, no one can claim to know all about Java after 1.5. It’s now 1.7 (although majority of us are still with 1.6) and it’s even less likely. I am no exception.

Unlike JNI, JNA is a pure Java implementation which makes life much easier than JNI. I still remember the time I had to go through quite a few steps between Java and C++ to expose COM in Java application (I hope this does not mislead you but the JNA does not support COM and C++ for the moment).

Bothered by SLOW Web UI to manage vSphere? Want to manage ALL your VMware vCenters, AWS, Azure, Openstack, container behind a SINGLE pane of glass? Want to search, analyze, report, visualize VMs, hosts, networks, datastores, events as easily as Google the Web? Find out more about vSearch 3.0: the search engine for all your private and public clouds.

Nothing comes for free though. While JNA is easier to implement, its performance is not as good as JNI. The reason is that the data conversation happens in Java with JNA, versus in C/C++ with JNI. For most of the applications, I think JNA is good enough in terms of performance. That’s why it’s selected in the libvirt Java binding.

With JNA, you still need to develop native implementation if that is part of your system scope. That is not always the case. If you have third party C libraries already, JNA would be a perfect choice.
Note that JNA is not the only alternative. A newer project called bridj (don’t take it as birdj as I did the first time) was inspired by JNA and performs better than JNA with more functionalities like COM, C++, etc. As I read through it, different platforms require different jar files. That works fine but would add more work in release and maintenance. Unless performance cannot be satisfied by JNA, I would pick JNA over BridJ for most projects.

HelloWorld Sample
Although it’s not required to know JNA as libvirt API developer, I was just curious how JNA can be used. So I took a bit of time to read a few Web pages and gone through a few samples.

The following is one that is adapted from the Wikipedia page. To run the sample, you want to download the jna.jar from the project home.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
 
interface CLibrary extends Library 
{
  static CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
  void printf(String format, Object... args);
}
 
public class JnaTest 
{
  public static void main(String[] args) throws InterruptedException 
  {
    int TOTAL = 1000;
 
    long start = System.currentTimeMillis();
 
    for(int i = 0; i < TOTAL; i++)
    {
      CLibrary.INSTANCE.printf("Hello, World 1\n");
    }
 
    long start2 = System.currentTimeMillis();
 
    for(int i = 0; i < TOTAL; i++)
    {
      System.out.print("Hello, World 2\n");
    }
 
    long end = System.currentTimeMillis();
    System.out.flush();
 
    Thread.sleep(1000);
 
    System.out.println("***** ratio: ***** " + (start2-start)/(end-start2));
  }
}

Optimize Performance
While loadLibrary() works just fine, there is another method register() that works faster. Per this page, you can use the API as in the following example which does pretty much the same thing as the previous example but with register method.

As I noticed, the register() seems less compatible than the loadLibrary(). The variable arguments in printf(), for example, does not work. If these are removed, the binding works fine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import com.sun.jna.Native;
import com.sun.jna.Platform;
 
public class JnaTestWithRegister 
{
  public static void main(String[] args) throws InterruptedException 
  {
    HelloJNA hj = new HelloJNA();
 
    int TOTAL = 1000;
 
    long start = System.currentTimeMillis();
 
    for(int i = 0; i < TOTAL; i++)
    {
      hj.printf("Hello, World 1\n");
    }
 
    long end = System.currentTimeMillis();
    long time1 = end - start;
 
    long start2 = System.currentTimeMillis();
 
    for(int i = 0; i < TOTAL; i++)
    {
      System.out.print("Hello, World 2\n");
    }
 
    long end2 = System.currentTimeMillis();
    long time2 = end2 -start2;
 
    System.out.println("***** ratio: ***** " + ((double)(time1))/((double)(time2)));
  }
}
 
class HelloJNA 
{
  //public static native void printf(String format, Object... args);
  public native void printf(String format);
 
  static
  {
    Native.register((Platform.isWindows() ? "msvcrt" : "c"));
  }
}

Comparing Performance Numbers
The typical JNA call takes about 1 ms. The first example shows about 20 time performance difference for the JNA and the standard Java System.out.println() method. For the second example with register method, it’s about 1 and sometime less. The performance advantage of using register method is quite obvious and should be the preferred approach if you are OK with its not supporting variable arguments.

This entry was posted in Software Development and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

  • NEED HELP?


    My company has created products like vSearch ("Super vCenter"), vijavaNG APIs, EAM APIs, ICE tool. We also help clients with virtualization and cloud computing on customized development, training. Should you, or someone you know, need these products and services, please feel free to contact me: steve __AT__ doublecloud.org.

    Me: Steve Jin, VMware vExpert who authored the VMware VI and vSphere SDK by Prentice Hall, and created the de factor open source vSphere Java API while working at VMware engineering. Companies like Cisco, EMC, NetApp, HP, Dell, VMware, are among the users of the API and other tools I developed for their products, internal IT orchestration, and test automation.