In this post I am sharing solutions for some problems I have faced while studying Java Native Interface (JNI). Pretty much the same steps found at http://java.sun.com/docs/books/jni/html/start.html were implemented, since I needed the simplest case study possible. Although this study is a Java experiment it involves several other technologies. Moreover, we’ll be compiling platform-dependent code (the C++ part of it), which means that the the architecture of the operational system and the version of the JVM where our final JNI program will be executed definitely matters. Please take a look at the list below and keep in mind that some of the issues we’ll go through are specifically associated to this environment.
- Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
- Java HotSpot(TM) 64-Bit Server VM (build 11.0-b16, mixed mode)
- Eclipse IDE for Java Developers Build id: 20100218-1602
- Microsoft Visual Studio Professional 2010
- Microsoft Windows Vista Ultimate 64 SP2
The program we will implement is a Hello World where the Java class will invoke a native method that prints “Hello World” out, the real implementation of the method will be done in C++, and compiled into a Windows (64-bit) binary DLL (Dynamic Link Library) file.
The Java Program
Step #1 — The Java class with a native
method
I chose to use Eclipse because it helps to save time and it’s my favorite Java IDE. A Java project was created and our Java class (the one with the native method) stored under the package structure I use to organize my Java code, in this example our class is called “HelloWorld” and lives in the package com.zilotti.studies.jni.helloworld
.
/**
* Class with a native method.
*
* @author Ivan Zilotti Alencar
* @author $Author$
* @version $Revision$
*/
public class HelloWorld
{
/**
* Native method
*/
private native void print();
static
{
final String LIBRARY_NAME = "HelloWorld";
System.loadLibrary(LIBRARY_NAME);
}
public static void main(String[] args)
{
new HelloWorld().print();
}
}
[/java]
Step #2 — Compile the Java class
Since I used Eclipse, the Java class was automatically compiled into the “bin” directory of the project. For example, a command line for compiling it could be javac comzilottistudiesjnihelloworldHelloWorld.java
(issued from the “src” directory of the aforementioned Java project).
Step #3 — Create Native Method Header File
The most important point here is issuing the command below in Windows Command shell. Please note that the current directory is our project’s “bin”ary output directory. It will contain only the “com” directory before the command is issued. After successfully issuing the command below, one will also find a new file, com_zilotti_studies_jni_helloworld_HelloWorld.h
, created by javah.
javah -jni com.zilotti.studies.jni.helloworld.HelloWorld
Step #4 — Open the C header file
The C header file generated by javah contains information about the native method we will implement in C++. We are all set to start working on the C++ project!
The C++ Library
Step #1 — Create a new “Win32” Project in Microsoft Visual Studio
Step #2 — Application settings and other options…
If you made it to this screen and pressed the “Finish” button shown on the Figure 6, you are ready to add the C header to the C++ project.
Step #3 — Add javah Generated Header to the C++ Project
Step #4 — Add JNI headers to the C++ Project
In order for native methods implemented in C++ to be properly invoked the jni.h header file must be included, it can be found in the JDK. The command shown in the Figure 10 can help you to identify the location of your current JDK.
Searching for the jni.h header file in the JDK…
Step #5 — Write the Native Method
[cpp] // HelloWorld.cpp : Defines the exported functions for the DLL application.//
#include <jni.h>
#include <stdio.h>
#include "stdafx.h"
#include "com_zilotti_studies_jni_helloworld_HelloWorld.h"
JNIEXPORT void JNICALL
Java_com_zilotti_studies_jni_helloworld_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!n");
return;
}
[/cpp]
Step #6 — Change Target Platform to x64
Step #7 — Building the C++ Project
Running the Java Program
Now we have the 2 major components required to execute our project: the Java program which simply specifies the native method; and the native implementation, bundled in the DLL file we have just compiled.
Very interesting!