JNI is the abbreviation of Java Native Interface . Starting with Java 1.1, the Java Native Interface (JNI) standard is part of the Java platform, allowing Java code to interact with code written in other languages. JNI was first designed for locally compiled languages, especially C and C + +, but it does not prevent you from using other languages, as long as the calling convention is supported.
Using Java to interact with locally compiled code typically loses platform portability. However, in some cases this is acceptable and even necessary, such as using some old libraries, interacting with hardware, operating systems, or improving program performance. The JNI standard ensures that local code can work at least under any Java Virtual machine implementation.
The design purpose of JNI (Java Native Interface)
· The standard Java class library may isn't support the platform-dependent features needed by your application.
· You could already have a library or application written in another programming language and your wish to make it accessible t o Java Applications
· You could want to implement a small portion of time-critical code in a Lower-level programming language, such as assembly, a nd then have your Java application call all these functions
Ii. The writing Steps of JNI (Java Native Interface)
• Java classes that write methods with native declarations
• Compile the Java class written using the Javac command
• Generate a header file with an extension of H using the Javah. JNI Java class name
• Implement a Local method using C + +
• Generate a dynamic connection library of files written by C/C + +
1) Writing Java programs:
Here take HelloWorld as an example.
Code 1:class HelloWorld {
public native void Displayhelloworld ();
static {
System.loadlibrary ("Hello");
}
public static void Main (string[] args) {
New HelloWorld (). Displayhelloworld ();
}
}
Declaration Native method: If you want to use a method as a local method, then you must declare that the change method is native and cannot be implemented. The parameters and return values of the method are described later.
Load Dynamic Library: system.loadlibrary ("Hello"); Load dynamic Library (we can understand this: our method Displayhelloworld () is not implemented, but we use it directly below, So you have to initialize it before you use it. This is typically loaded with a static block. Also note that the system.loadlibrary () parameter "Hello" is the name of the dynamic library.
The main () method is the entry point to the function.
2) compiling
Javac Helloworld.java
3 Generate a header file with an extension of H
Javah HelloWorld
Header file Contents:/* Do not EDIT This file-it is machine generated * *
#include
/* Header for class HelloWorld * *
#ifndef _included_helloworld
#define _included_helloworld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:helloworld
* Method:displayhelloworld
* Signature: () V
*/
Jniexport void Jnicall Java_helloworld_displayhelloworld (jnienv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
(Here we can understand this: This H file is equivalent to our interface in Java, where we declare a java_helloworld_displayhelloworld (JNIENV *, jobject); And then implement this method in our local approach, which means that the method name we use when writing C + + programs must be the same as here.
4 Write the Local method (C + + program)
Implement the same method as the method name declared in the header file generated by the Javah command.
Code 2:1 #include "jni.h"
2 #include "HelloWorld.h"
3 #include ...
4 jniexport void Jnicall Java_helloworld_displayhelloworld (jnienv * env, Jobject obj)
{
printf ("Hello world! " );
return;
}
Note that line 1th requires that the jni.h (which can be found under the%java_home%/include folder) be introduced, because the types of jnienv, Jobject, and so on in the program are defined in the header file;
Also in line 2nd need to introduce the HelloWorld.h header file (I understand: the equivalent of when we are writing a Java program, the implementation of an interface needs to be declared, here is the HelloWorld.h header file declaration method to implement. Not necessarily, of course. And then save it for helloworldimpl.c OK.
5 Generating dynamic libraries
Here, for example in Windows, you need to generate a DLL file. Under Save the HELLOWORLDIMPL.C folder, use the VC compiler CL generation.
The command line is as follows: Cl-i%java_home%/include-i%java_home%/include/win32-ld Helloworldimp.c-fehello.dll
Note: The generated DLL filename is configured after the option-fe, which is Hello, because the name we loadlibary in the Helloworld.java file is hello. Of course, there are changes to be done here. Additional-i%java_home%/include-i%java_home%/include/win32 parameters need to be added because the jni.h file was introduced when the local method was written in step fourth.
6) Running the program
Java HelloWorld is OK.
Summary Use examples of JNI (Java Native Interface)
The following is a simple example to achieve the function of printing a sentence, but with the C of printf final implementation. The JNI interface typically provided to Java includes an so file (which encapsulates the implementation of the C function) and a Java file (a class that needs to call path).
1. The goal of JNI is to make it possible to invoke some functions of the C implementation, such as the following Java class, to invoke a local function testjni (generally declared private native type), first you need to create a file Weiqiong.java, which reads as follows: Class Weiqiong
{
Static
{
System.loadlibrary ("Testjni"); Load a static library in which the test function implements
}
Private native void Testjni (); Declaring a local call
public void Test ()
{
Testjni ();
}
public static void Main (String args[])
{
Weiqiong haha = new Weiqiong ();
Haha.test ();
}
}
2. Then execute Javac weiqiong.java, and if there is no error, a weiqiong.class will be generated.
3. Then executing Javah weiqiong, a file Weiqiong.h file is generated, with a function declared as follows: Jniexport void Jnicall java_weiqiong_testjni (jnienv *, jobject);
4. Create file Testjni.c The above function is implemented, as follows: #include "jni.h"
#include weiqiong.h jniexport void Jnicall java_weiqiong_testjni (jnienv * env, Jobject obj)
{
printf ("Haha---------go into c!!!");
}
5. To generate the. So file, create the makefile file as follows:
LIBTESTJNI.SO:TESTJNI.O Makefile
Gcc-wall-rdynamic-shared-o libtestjni.so TESTJNI.O
TESTJNI.O:TESTJNI.C weiqiong.h
Gcc-wall-c testjni.c-i./-i/usr/java/j2sdk1.4.0/include-i/usr/java/j2sdk1.4.0/include/linux
Cl:
RM-RF *.O *.so
Note: GCC is in front of the tab empty, J2SDK directory according to their own J2SDK specific version to write, the resulting file must be the name of the LoadLibrary parameter name plus "Lib".
6. Export Ld_library_path=., this sets the LIBRARY path to the current directory so that the Java file can find the so file. It is common practice to copy so files to the Ld_library_path directory of this machine.
7. Execute Java weiqiong, print out the result: "Haha---------go into c!!!"
Four. Problems considered in JNI (Java Native Interface) calls
There are some questions when using JNI for the first time, and then one by one in use, and here is the memo for these questions:
1. How Java and C are interoperable.
In fact, the main reason for interoperability is the data type problem, JNI solved the problem, such as the C file jstring data type is a Java incoming string object, after the transformation of the JNI function can become the char* of C.
The corresponding data types relate to the following table:
Java type |
Local C type |
Description |
Boolean |
Jboolean |
Unsigned, 8-bit |
Byte |
Jbyte |
Unsigned, 8-bit |
Char |
Jchar |
Unsigned, 16-bit |
Short |
Jshort |
Signed, 16-bit |
int |
Jint |
Signed, 32-bit |
Long |
Jlong |
Signed, 64-bit |
Float |
jfloat |
32-bit |
Double |
jdouble |
64-bit |
Void |
Void |
N/a |
JNI also contains a number of reference types that correspond to different Java objects
2. How do I convert Java incoming string argument to char* of C and use?
The string parameter that is passed in Java, converted to jstring data type in c file, declared char* test in C file, and then test = (char*) (*env)->getstringutfchars (env, Jstring, NULL) Note: When Test is finished, notify the virtual machine platform that the code does not need to be accessed again: (*env)->releasestringutfchars (env, jstring, test);
3. Pass the buffer of a char* obtained in C to Java.
If this char* is a generic string, it can be passed back as a string. If it contains a '/0 ' buffer, it is best to bytearray out as a copy of length, if copy to string, possibly to '/0 ' truncated.
There are two ways to pass the resulting data:
One is to directly new in JNI a byte array, and then call the function (*env)->setbytearrayregion (env, ByteArray, 0, Len, buffer); Copy the value of the buffer to the ByteArray , the function directly return ByteArray on it.
One is the return error number, the data is passed as a parameter, but the basic data type of Java is the pass value, the object is the passing reference, so the byte array that needs to be outgoing is wrapped in a class, as follows: