Sitemap

Step Into JAVA Native Programming

--

What is Java Native or Java Native Interface (JNI)?

JNI is a mechanism or a feature that facilitates to call of functions in a different language like C or C++ program.

NOTE: JNI currently facilitates for C or C++ function invocation.

Reasons for using JNI!

  • Access to handle system native features which is not possible to achieve via JavaAPI.
  • Access to legacy codes of a particular system for example: Accessing and using WIN32 API or Overriding Windows Callback functions.
  • For processing algorithms that need high performance, this is not an issue with later versions of the JVM editions.

Is it possible to use languages other than C and C++?

JNI doesn’t provide functionality other than C and C++, yet there might be third-party APIs that facilitate other languages like Delphi.

Alternative Solution:

Many languages that implement native access mostly choose to use C or C++ therefore functions for other languages can be developed by C and C++ and facilitate to access features via C or C++ is possible.

Compatibility and portability issues when using JNI

As the word says “Native” you must realize that code developed for the system is unique to the system itself therefore you need to create the same functions for other Platform with the related API, for example:

The native function created for Windows OS doesn’t work on Mac OS therefore you need to create a different version for Mac OS this means Java Application is OS Dependent.

Steps in Brief for Using JNI

Step 1:

Create a class and declare methods with the “native” keyword

Important: native method signature is like abstract methods; therefore declare methods without a body as in the preceding example:

public native void myNative();

Step 2:

Compile the java class containing the native methods, then generate C header file using “javah” tool located in “X:\Program Files\Java\jdkxxx\bin\”

This will generate a header file containing function prototypes in C styles that you will override them to implement native code.

Run cmd
Type set path = X:\Program Files\Java\jdkxxx\bin\” then enter
javah <ClassName>

Know you will get C style header file like this “<ClassName>.h, this will later used to create a DLL that your java application can load with System.loadLibrary(“MyDLL”);

IMPORTANT: the javah generated a header file containing prototype functions in static form therefore DLL type must be a static DLL which will be explained later.

Step 3:

Create a C or C++ DLL:

For creating a DLL you can use Visual C++, Qt, RAD Studio.

Example: Simple Program with JNI integration.

In this example I will demonstrate how to integrate JNI with a Java application, creating a Static DLL with Visual C++, I’m going to use Visual C++ 2013 version yet there is no issue with using later versions like 2008, 2010 same as with 2013 version, Eclipse will be used to create the Java Application.

This example is intended to demonstrate the most basic functionality by performing a simple calculation with C++ and output in Java data representation then delegating the value (return by C++ function) to the Java native method so the JVM can retrieve the value implicitly.

Create Java Project:

I’m currently using Eclipse IDE to demonstrate this example.

Step 1:

File — New — “JAVA Project” dialog will open as below then name your project and click “finish”.

Step 2:

After creating a project create a package (right click on src choose package or file — new — package) “com.srg.mynatives” as preceding or with any name,

The reason to use packages is that it’s somewhat different when native method prototype declarations when the java classes containing native methods were within a package, so I’m going to demonstrate that too.

Press enter or click to view image in full size

After that create another package “com.srg.test”.

Step 3:

Create a java class “MyNatives.java” for native method declaration in “com.srg.mynatives”.

The source code should be as the one specified here:

package com.srg.mynatives;
public class MyNative {
//Declare native methods.
public native double getTotal(double val1, double val2);

}

Step 4:

Create a Visual C++ DLL project, for this scenario, I’m using Visual C++ 2013 version.

File –> New –> Project

Press enter or click to view image in full size

This DLL uses the Microsoft Foundation Class (MFC) library therefore when distributing a Java application with an MFC DLL you may need to install Visual C++ Redistributable appropriate version, in my case I need to install Visual Redistributable 2013 x64 or x86 depending on the DLL processor architecture.

Specify a name for your project and save it to a location then click “OK”

Then “MFC DLL Wizard” will open click “Next”

Press enter or click to view image in full size

Select DLL type “Regular DLL with MFC statically linked” literally that is a “Static DLL” with MFC support.

The benefit of choosing this option is dependencies used are included in the DLL therefore DLL is large in size and you may not need to distribute some dependencies (or DLLs) separately.

Press enter or click to view image in full size

Click “Finish”,

After that project will start creating and may take some time to parse classes and generate the project.

Step 5:

Generate “C” style header file for “MyNative.java” using “javah.exe” tool

For this to perform first you must compile the “MyNative.java” and then specify the “MyNative” class name to “javah.exe” tool to generate the header file.

Run in command line type: set path=D:\Program Files\Java\jdk1.7.0_45\bin
Press enter or click to view image in full size

Know set the folder environment where the compiled classes exist in the Eclipse project

In my case, it’s in “G:\Java Research Lab\Projects\JNIBasics\bin”

Get Roshan Gerard’s stories in your inbox

Join Medium for free to get updates from this writer.

Set path as preceding “cd G:\Java Research Lab\Projects\JNIBasics\bin” enter then change the driver to “G:”

Press enter or click to view image in full size

After that generate the header file as described, as I said earlier regarding the packages there is the part that demonstrates how to generate a header file for a class in the package.

“javah com.srg.mynatives.MyNative “ enter then the header will generate with the name “com_srg_mynatives_MyNative.h” You can change the name if you like.

As you can see the class name is specified in the package declaration.

Press enter or click to view image in full size

I’m changing the name of the generated header file to “MyHeader.h”

Step 6:

Adding header file to Visual C++ project

Copy the header file into the Visual C++ project folder’s solution folder’s folder in the project name

My project is as below:

“x:\StepIntoJNI\StepIntoJNI_s\StepIntoJNI\MyHeader.h”

The solutions folder is “StepIntoJNI_s”

After that add the header file to your project from the “Solution Explorer”

From the “Solution Explorer” — Right click on “Header Files” node — Add — Existing Item.

Press enter or click to view image in full size

From the “Add Existing Item” dialog select the “MyHeader.h” and click “Add”

Press enter or click to view image in full size

Step 7:

Add JNI library locations to Visual C++ project.

From “Solution Explorer” — Right click on <project_name> — select “Properties”.

Press enter or click to view image in full size

In the project properties dialog navigate to “VC++ Directories — Include Directories — click on the drop-down arrow and select “<Edit>”

Press enter or click to view image in full size

In the “Include Directories” dialog click on “folder” icon then add “JNI” library locations

Currently, there are two locations to define, include libraries were exist in the JDK folder,

There are two locations as below:

“D:\Program Files\Java\jdk1.7.0_45\include”

“D:\Program Files\Java\jdk1.7.0_45\include\win32” then click “OK” and save settings.

Step 8:

Create a “.CPP” file to override the “C” style prototypes in the “MyHeader.h” file

From “Solution Explorer” — Right-click on the “Source Files” node — Add — New Item.

Press enter or click to view image in full size

From the “Add New Item” dialog Navigate to “Visual C++” — Select “C++ File (.cpp)”, Specify name for the CPP file I’m just naming it as “MyCPP.cpp” then click on “Add”.

Press enter or click to view image in full size

Step 9:

Overriding the prototype functions in the “MyCPP” source file.

Open “MyCPP” from the “Solution Explorer” and then specify the code as below.

#include "stdafx.h"	 //This should be included.
#include <jni.h> //This should always include on every CPP file that "MyHeader.h" included.
#include "MyHeader.h"
JNIEXPORT jdouble JNICALL Java_com_srg_mynatives_MyNative_getTotal(JNIEnv *env, jobject object, jdouble val1, jdouble val2){
return (val1 + val2);
}

Finally, save the project.

Step 10:

Build configuration for the DLL,

DLL to work with the current architecture that JVM runs at x86 or x64 the DLL must be the same architecture as the JVM architecture.

From “Main Menu” — “Build” — Click on “Configuration Manager”.

Press enter or click to view image in full size

In the “Configuration Manager” dialog choose “<New>….” from the “Active solution platform” combo box.

Press enter or click to view image in full size

In the “New Solution Platform” dialog choose a desired platform between “x86 (Win32)” This is default created or x64 I’m choosing x64 because my JRE is x64.

Then click “OK”.

Finally build the DLL: Main Menu — Build — Click on “Build Solution” then DLL will be generated in the path as preceding “x:\StepIntoJNI\StepIntoJNI_s\x64\Debug”.

Step 11:

Copy the generated DLL to Eclipse project location “x: \JNIBasics\”.

Press enter or click to view image in full size

Open the eclipse project “JNIBasics” and create a new class called “Test.java” in “com.srg.test” package as in the figure.

Press enter or click to view image in full size

Open the “Test.java” and then add the code specified below.

package com.srg.test;
import com.srg.mynatives.MyNative;/**
*
* @author Roshan Gerard Bolonna
*
*/
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
/*
* Load the DLL at the startup, before invoking any native methods.
*/
System.loadLibrary("StepIntoJNI");

MyNative myn = new MyNative();
double total = myn.getTotal(50, 45.54);
System.out.println("Natively Performed Calculation: "+total);
}}

When executed output will be as in the below figure.

Press enter or click to view image in full size

The End….!

This is my first post published through LinkedIn, regarding Java Native Programming an introductory tutorial, that contains very simple examples with in-depth guidance for starters.

Hope this will be a good tutorial for programmers who like building their components who would like to do things differently and innovatively and embrace developing system software.

Please feel free to message me via LinkedIn regarding any misconceptions or errors in this post

Thank you…!

Example Project Sources

--

--