JNI Hello World
Hi every body. This is my first post. I hope you guys like. In this first post I will show how to declare, implement, compile and call a native Java methods in Linux.
The first thing we need is a class with a native method. I chose a static one for sake of simplicity. We’ll see instance methods later on anoter post.
Our class will look like this:
A litle bit of explanation doesn’t hurt any body right? So here we go… This first block load our native code. In linux this will try to load a library called “libhelloworld.so”. More on this later.
This block will load our native code as soon as our class get loaded by class loader.
The next line declares our native method. This method will be implemented at libhellonativeworld.so.
And after that we call it at our main:
Now we need to compiled it. Nothing new here:
If you try to call this class you’ll get an error. Let’s take a look:
This means that java can’t find libhellonativeworld.so. We’ll create it soon but first we need to create a header for our library. This header is created by javah tool. This tool is called against a compiled class. This is why we compile our class before going furter to native code. The header can be generated with this command:
This command will generate the HelloJNIWorld.h header file. This header will look like this:
As said at first line of the file, you should not edit this file. This is because generating it again will override your modifications. You can see that it declares our native method with some weird naming. The naming pattern is explaned at JNI’s documentation . You don’t have to botter to that namming pattern since javah tool deals with it for you. So the next step is defining our native method. To do this we will create a new file, named libhellonativeworld.c. At this file goes the body of our native method, function, what ever … You should include the header generated by javah and copy the prototype that was created for you, this will save you from typos, remeber to name the parameters :).
Our method will simply print a message, but from native code. So here it is:
Okay now its time to copile our native code, but first there is someting that
need to be known. The header generated by javah
include two headers. That
headers can be found at JAVA_HOME/include and JAVA_HOME/include/linux, if
you’re running in linux as I expect you to be. Well, I’m running Fedora 24 and
here I can found it at /etc/alternatives/java_sdk. I will declare JAVA_HOME to
point there. This can be done like this export
JAVA_HOME=/etc/alternatives/java_sdk
. After this compiling is a simple
matter of:
Now we have everything we need. Let’s try to run our native code:
Why this error again!? Well there is one little step missing. We have libhellonativeworld.so but java can’t find it. There is a bunch of ways to do this. You can move that library to some standard folder like /usr/lib. You can declare LD_LIBRARY_PATH to the folder where it resides, or you can use java.library.path property at command line. Let’s try the last:
There you go. Last but not least. Doing all that commands by hand can be tedious so let’s create a Makefile to hold all that mess. It’ll look like this:
Pretty crypt doesn’t? These are called “pattern rules” and are topic for another post. I hope that this post help you to have an “in mind” road map about how native code is handled by Java. Everything you need to know can be found at documentation. All the code can be found at here
Cheers!