Switch to full style
Java2 codes,problems ,discussions and solutions are here
Post a reply

JNI Basics lesson 1

Sat Nov 08, 2008 8:50 am

How to use JNI in java?
Java design allows you to run other programming languages such as C/C++ and assembly. Java keyword "native" is used to mark methods that is implemented in other languages. You only just have to load the external libraries into your java code and run it. This type of handling is called using java native interface(JNI). JNI saves the time of rewriting specific libraries in java by increasing the usability of the already developed native ones. In this example we illustrate the basic concept of JNI by taking a snippet of java project to connect a serial PC port with help of a C++ functions.
Hints about Java Native Interface
  • Use native keyword to mark functions.
  • Calling native functions make has affects on the speed.
  • You can use Windows APIs.
  • Your program may not run on a specific operating systems.
  • Your application may has network problems.
  • Usually take more to debug and handle errors in native functions.
  • You have to use DLL file because it contains the functions implementation.
  • In way to compile the DLL file you have to build .h file for your java file.

We use example of calling serial port I/O C++ functions from java code. Functions used :
java code
// Opens the serial port and returns the port handle.  The port handle is stored for use in the //_read/_write calls.
native int _openSerialPort(String comPort, int baud, int dataBits, int stopBits, int parity);

// Write the bytes in 'data'. Returns the number of bytes written
native int _writeSerialPort(int port, byte data[]);

native int _writeSerialPortByte(int port, byte bit);

// Reads all available bytes in the serial port buffer. If nothing available, returns a zero-length array.
// Note this function never blocks -- it always returns immediately.
native byte[] _readSerialPort(int port);

native int _readSerialPortByte(int port);

native void _closeSerialPort(int port);

We send the input port number as functions parameters and we get integers and byte[] arrays in some cases. To be able to use these native functions you have first to load the libraries DLL which combines the related C++ files and contains its implementation. In the used example, the functions prototypes and library call exists in a file "SimpleSerialNative.java". In following snippet static block we load the library using "loadLibray" function. The DLL file loaded is "simpleserialnative.dll". As you may knew that static block is executed once the class is loaded which means that the library is loaded with the class. This DLL file exists within the same java project.
java code
class Test1
{
static
{
System.loadLibrary("simpleserialnative");
}
}

You can call another function which is

java code
System.load("simpleserialnative");

Note: sometimes you have to add the .dll file to JVM classpath. You can just put your DLL in any place and then use load() function to include it and remember that DLL file contains the implementation of native functions.

java code
native int _writeSerialPort(int port, byte data[]);

The first native function we have is _writeSerialPort. There is no body for this function and its is implemented in C++. Once you load the DLL file this function are going to be loaded and all the similar functions. When you call this function the JVM will executes its implementation and if it failed to load it an exception java.lang.UnsatisfiedLinkError are going to be thrown.

In goal to build up a DLL file for a c++ project, you have first to create a .h SimpleSerialNative.java file for it. You have to use javah.exe at bin JDK to create the .h file :
java code
Javah -jni SimpleSerialNative

The header file generated in our class case is:
cpp code
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class SimpleSerialNative */

#ifndef _Included_SimpleSerialNative
#define _Included_SimpleSerialNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: SimpleSerialNative
* Method: _closeSerialPort
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_SimpleSerialNative__1closeSerialPort
(JNIEnv *, jobject, jint);

/*
* Class: SimpleSerialNative
* Method: _openSerialPort
* Signature: (Ljava/lang/String;IIII)I
*/
JNIEXPORT jint JNICALL Java_SimpleSerialNative__1openSerialPort
(JNIEnv *, jobject, jstring, jint, jint, jint, jint);

/*
* Class: SimpleSerialNative
* Method: _readSerialPort
* Signature: (I)[B
*/
JNIEXPORT jbyteArray JNICALL Java_SimpleSerialNative__1readSerialPort
(JNIEnv *, jobject, jint);

/*
* Class: SimpleSerialNative
* Method: _readSerialPortByte
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_SimpleSerialNative__1readSerialPortByte
(JNIEnv *, jobject, jint);

/*
* Class: SimpleSerialNative
* Method: _writeSerialPort
* Signature: (I[B)I
*/
JNIEXPORT jint JNICALL Java_SimpleSerialNative__1writeSerialPort
(JNIEnv *, jobject, jint, jbyteArray);

/*
* Class: SimpleSerialNative
* Method: _writeSerialPortByte
* Signature: (IB)I
*/
JNIEXPORT jint JNICALL Java_SimpleSerialNative__1writeSerialPortByte
(JNIEnv *, jobject, jint, jbyte);

#ifdef __cplusplus
}
#endif
#endif

Just put this file within the java files directory. The next step is to create a DLL for your c++ codes. You can use visual basic C++/VisualCafe IDE wizards to compile it. You have to use the generated .h file in previous step in building the DLL file. Once you complete creating DLL file, just put it in the class path and start using it like our attached java netbeans project. Following in guidelines for used example :
    If you want to try to build a standalone application, you'll need some of the
    tools in this folder. It worked for me in VisualCafe 3.0, but stopped
    working in VisualCafe 4.0.

    If you rebuild the native DLL, and you want to rebuild SimpleSerialEXE.exe
    you must rebuild SimpleSerial.lib. The .lib file MSVC++ produces is in COFF
    format, which isn't understood by the Java compiler.

  1. Delete SimpleSerialNative.lib.
  2. Run implib.exe on SimpleSerialNative.dll. This program creates SimpleSerialNative.lib
    file based on the .dll
  3. Run the created SimpleSerial.lib through Coff2omf.exe to convert it from COFF to OMF
    format. NOTE: If you try and do this with the lib file created by the MS compiler, it
    will fail.
  4. Copy the .lib file to the SimpleSerial directory



Attachments
serialport.rar
(550.2 KiB) Downloaded 939 times

Re: JNI Basics lesson 1

Thu Jan 29, 2009 11:38 am

Dear Sir,

I have problem while calling functions from dll file.
I have a dll file & I know their proto types (function headers) of all functions used in dll file (I get it from user manual).

I want to call these functions by using dll file form Java Environment (.java file).

It does not give any error when I complie the .java file[>javac Sample.java ] but gives
following error message when I run the file [java Sample ]

Error Message
java.lang.UnsatisfiedLinkError exception

What is the possible reason/solution of this error?

waiting for quick response.

Regards
Muhammad Shahid Aslam

Re: JNI Basics lesson 1

Tue Jun 18, 2013 12:01 am

updated.

Post a reply
  Related Posts  to : JNI Basics lesson 1
 basics     -  
 Matlab basics examples     -  
 Html basics tutorials.     -  
 C++ Code Visual Basics.net 2003     -  
 Lets Learn C++----->(Lesson 5) Functions     -  
 Re: Lets Learn C++----->(Lesson 6) File I/O     -  
 Introduction to game programming. (Lesson 1)     -  
 Re: Lets Learn C++----->(Lesson 1) Introduction     -  
 Full Screen graphics (Lesson 2).     -  
 Re: Lets Learn C++----->(Lesson 2) Arrays     -  

Topic Tags

Java OOP