Interacting With C From Java With JNI: Part 1/2 - Java Native Methods
(Page 2 of 3 )
You can use Java native methods in your code whenever you need features that are not supported by the various Java libraries. You can also use native methods when an existing method already coded in another native programming language needs to be used in your Java applications.
Real Life ScenarioYou are an employee for Trident Infotech. Joe, your project manager has told you to code a method in your existing application (which is entirely in Java), which handles extremely low level tasks including interacting with your hardware. You, being an experienced Java coder, know that coding the method in Java will be a bit of a problem. You remember you had coded a method in C a few months back with the identical functionality.
Suddenly, you recall the concepts behind JNI. You call Joe (your project manager) and tell him the problem and its JNI based solution. He tells you to go ahead with it. You quickly make a few changes in that C method you had coded and also to your current Java project. You test the code and it works fine.
A JNI ExampleLet's start by creating the Java file from which we will call the native method. Save this code as NevNative.java in your favorite text editor:
public class NevNative {
public native void display();
static {
System.loadLibrary("nevnative");
}
public static void main(String[] args) {
NevNative object=new NevNative();
object.display();
}
}Simple isn't it? Well we are declaring the native method called display, which will be implemented in C (that's the reason we leave it empty here). In the main method we just make an object of our class and call that native method.
Ok, now does anyone have a clue what the following lines do?
static {
System.loadLibrary("nevnative");
}Did you know that this static code block is executed even before the constructor of the class? Why don't you try it? Create a simple Java file with a constructor and a static block both displaying some messages. Make an object of the class and see for yourself. What programmers do is they usually add all of the code related to loading libraries and classes in this static block so that when the actual execution starts, all of that code is loaded and ready to use.
Now that we know what exactly a static block does, let's leave this part of our code for now. I will explain what our static block does a bit later.
Before we proceed, let's compile the Java file which we just created:
C:\jdk\bin\javac workingdir\NevNative.javaAfter we successfully compile our Java file we need to create our C header file. We use the javah compiler to do so:
C:\jdk\bin\javah workingdir\NevNativeCheck your working directory and you will find a file called NevNative.h has been created. Go ahead, open it and have a look. Look for a line that starts like this:
JNIEXPORT void JNICALL Java_NevNative_display(JNIEnv *, jobject);This is the method declaration for the method we will have to implement in our C File. We will do that next.
Let's create out actual C file in which we will write the method body for our Java method called display. Save this code as NevNativeImp.c in your favorite text editor.
#include <jni.h>
#include "NevNative.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_NevNative_display(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}The C code is very simple. Take a quick look at our method declaration. This method decleration must be right. You should copy and paste it from the header file. The C code in the implementation of our function displays a simple message.
We can't forget to include the javah generated header file, the jni.h header file (when writing native methods you must never ever forget to include this file) and of course the stdio.h header file, which we need because we are using the printf function that is a part of the stdio.h library.
Since we have created our C file, let's go and compile it. Hold on, we don't need an EXE but we do need a DLL so that we can load it in our Java file to use. So, using your favorite C compiler, compile your C file into a DLL file and not an EXE. Call the DLL nevnative.dll.
The static block which I left for explaination should make more sense now. Let's have another look at it:
static {
System.loadLibrary("nevnative");
}Using the loadLibrary method in the System class, we load the nevnative.dll file we created earlier.
It's show time folks. Lets run our Java code to see whether things are working or not:
C:\jdk\bin\java workingdir\NevNativeIf you see that the message “HelloWorld” on your screen then everything has worked as planned. It's really cool to see two different programming languages talking to each other like this, but hold on for a second. JNI has a lot more to it than this.
What happens when you need to pass parameters to the native methods or return values from native methods? You must have also noticed that the method declaration in C has a few extra parameters created by default? What are those all about?
I'll leave all of this for my next article, in which we will delve further into JNI. The main purpose of this article was to provide you with an introduction to what JNI is, so hopefully I've done just that.
Next: Conclusion >>
More Java Articles
More By Neville Mehta