Search this site

 Home  JNI Intro  JNI data types  JNI overhead

Search this site:
Threads Database Profiling Regular expressions Random numbers Compression Exceptions C Equivalents in Java

 What do you think of this article? Did it help you? Found a mistake? Feedback and suggestions here

The Java Native Interface (JNI)

Java provides a framework called the Java Native Interface (JNI), with which it is possible to write native methods. A native method is a method that is mapped to a function in a library of native code, such as a DLL under Windows. Or, to put things more simply, you can write code in C or C++1 and call it from Java.

When do you need to use a native method?

The usual reasons for writing a native method are:

  • to access facilities of the operating system not provided via the standard Java libraries;
  • you have some library or code already written in C/C++ that you want to interface with without porting it to Java;
  • in a few rare cases where there is a proven performance benefit (e.g. because you know your particular C compiler can optimise some particular code better than the JVM's JIT compiler).

The benefits of using native code may need to be weighed up against the resulting loss in portability, security and codability.

Caveat: beware false performance assumptions

If you are porting code from Java to C purely because of a believed performance gain, it is worth considering whether the gain is actually real and whether it is really attributable to using native code. The JIT compilers built into modern JVMs such as Hotspot already perform a large number of optimisations, for example:

  • modern JIT compilers can perform various optimisations such as loop unrolling, escape analysis and "architecture savvy" optimisations (e.g. re-ordering instructions to take advantage of parallelism built into a particular CPU) just like regular compilers;
  • accesses to Java object fields can compile to load/store machine instructions;
  • basic maths operations often compile directly to floating point machine instructions;
  • operations on ByteBuffers generally compile directly to load/store machine instructions.

Some cases where native code is apparently "faster" than its Java counterpart turn out to be false comparisons. For example, if you have a List of Java objects which you then code in C as an array of structs, the C version does away with some overhead from object housekeeping and garbage collection. However, this optimisation isn't tied to the language per se: you could also do away with that overhead in Java by storing all the data records one after the other in a big ByteBuffer (perhaps the nearest equivalent to an array of structs).

Later on in this section, we look in more detail at typical JNI call overhead.

Requirements for writing native methods

Having carefully the pros and cons, if you are still convinced that you need to write native methods, then the essential requirement is a C compiler than can produce a dynamic library on your particular platform (e.g. a DLL in Windows) and which can compile against the libraries that you need to use. Possible choices include Eclipse, Visual Studio under Windows, or for diehards, running gcc/cc from the command line.

In this tutorial, we include a few practical examples from Visual Studio. However, the general principles we illustrate apply to other compilers.

Next: getting started with JNI

On the next page, we look at how to get started with JNI and the stages involved in setting up a DLL/dynamic library project and writing our first native method.

1. C or C++ are the most popular choice for writing native methods to be called from Java, and the JDK provides a tool to help with writing them in C/C++. But in principle, you should be able to write native methods in any language that you can compile into a dynamic library on your particular platform.

Written by Neil Coffey. Copyright © Javamex UK 2009. All rights reserved.