Getting to know JNI for the first time

1. Concept

JNI is the abbreviation of Java Native Interface, which means Java Native Interface. The JNI technology realizes the mutual call between Java programs and local application programs. Usually, the local program here refers to the application program written in C or C++ language. From the name of JNI, we can know that this technology is implemented through interfaces. The advantage of interface programming is that it has high scalability and can also ensure the cross-platform characteristics of Java. Using JNI has the following advantages. First, you can directly use the previously defined Naitive module to avoid repeated wheel building; second, it can improve the running efficiency and speed of the program; third, it can improve the security of the program and increase the difficulty of decompilation.

Second, use

1. Load the JNI library

If Java wants to call Native functions, it must be done through a dynamic library located at the JNI layer. As the name implies, a dynamic library is a library loaded at runtime, so when and where is this library loaded?
There is no standard answer to this question. In principle, it can be loaded at any time and anywhere before calling the Native function. The common practice is to load in the static statement of the class by calling the System.loadLibrary method. The parameter of the System.loadLibrary function is the name of the dynamic library. The system will automatically expand it to the real dynamic library file name according to different platforms. For example, it will expand to libname.so on Linux systems, and it will expand to libname on Windows platforms. .dll. For details, please see the demo of the following code:

// 加载JNI库
static {
    System.loadLibrary("hello_jni");
}

2. Declare the Native function

Java provides the native keyword for declaring a Native function. Like declaring an interface, we do not need to provide a specific implementation for the Native function.

// 声明一个Native函数。native为Java的关键字,表示它将由JNI层完成。
public static native void sayHello();

3. Call the Native function

Just like a normal Java function call, you can call it directly. So far the Java layer code has been written, the code is as follows:

public class HelloJNI {

    // 加载JNI库
    static {
        System.loadLibrary("hello_jni");
    }

    // 声明一个Native函数。native为Java的关键字,表示它将由JNI层完成。
    public static native void sayHello();

    // 在main函数中调用Native函数
    public static void main(String[] args) {
        sayHello();
    }
}

4. Compile and generate header files

1) Enter the directory where HelloJNI.java is located, and use the javac HelloJNI.javacommand to compile the Java source file
2) Use the javah HelloJNIcommand to generate the HelloJNI.h header file in the current directory
3) The following is a demonstration of the operation on the linux system:

yqm@unbuntu:~$ cd Desktop/JNIDemo/
yqm@unbuntu:~/Desktop/JNIDemo$ javac HelloJNI.java 
yqm@unbuntu:~/Desktop/JNIDemo$ ll
总用量 16
drwxrwxr-x 2 yqm yqm 4096  57 09:14 ./
drwxr-xr-x 9 yqm yqm 4096  57 09:13 ../
-rw-rw-r-- 1 yqm yqm  441  57 09:14 HelloJNI.class
-rw-rw-rw- 1 yqm yqm  364  57 09:13 HelloJNI.java
yqm@unbuntu:~/Desktop/JNIDemo$ javah HelloJNI
yqm@unbuntu:~/Desktop/JNIDemo$ ll
总用量 20
drwxrwxr-x 2 yqm yqm 4096  57 09:14 ./
drwxr-xr-x 9 yqm yqm 4096  57 09:13 ../
-rw-rw-r-- 1 yqm yqm  441  57 09:14 HelloJNI.class
-rw-rw-r-- 1 yqm yqm  372  57 09:14 HelloJNI.h
-rw-rw-rw- 1 yqm yqm  364  57 09:13 HelloJNI.java
yqm@unbuntu:~/Desktop/JNIDemo$ cat HelloJNI.h 
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */

#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloJNI_sayHello
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif
yqm@unbuntu:~/Desktop/JNIDemo$ 

4. Implement Native functions in C or C++

You can see that the header files automatically generated using the javah command have generated corresponding C and C++ function declarations for the Native functions we defined in the Java code. Therefore, we only need to use C or C++ to import the header file and implement the corresponding function.

// filename -- HelloJNI.cpp
// 包含自动生成的头文件
#include "HelloJNI.h"
#include <iostream>

JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *, jclass)
{
    using namespace std;

    cout << "From HelloJNI.cpp :"
        << "Hello world !"
        << endl;

    return;
}

5. Compile the dynamic library

To compile a dynamic library in C++, use the command g++ -shared -fPIC -I <JAVA_HOME_DIR>/include -I <JAVA_HOME_DIR>/include/linux <filename>.cpp -o lib<filename>.so. It <JAVA_HOME_DIR>needs to be replaced with the installation directory of the jdk of this machine, and <filename>needs to be replaced with the name of the cpp file. Operation demonstration on linux system:

yqm@unbuntu:~$ cd Desktop/JNIDemo/
yqm@unbuntu:~/Desktop/JNIDemo$ ll
总用量 24
drwxrwxr-x 2 yqm yqm 4096  57 10:14 ./
drwxr-xr-x 9 yqm yqm 4096  57 09:13 ../
-rw-rw-r-- 1 yqm yqm  441  57 09:14 HelloJNI.class
-rw-rw-rw- 1 yqm yqm  265  57 10:12 HelloJNI.cpp
-rw-rw-r-- 1 yqm yqm  372  57 09:14 HelloJNI.h
-rw-rw-rw- 1 yqm yqm  364  57 10:11 HelloJNI.java
yqm@unbuntu:~/Desktop/JNIDemo$ g++ -shared -fPIC -I /home/yqm/EnvTools/java-1.8.0-openjdk-amd64/include -I /home/yqm/EnvTools/java-1.8.0-openjdk-amd64/include/linux HelloJNI.cpp -o libhello_jni.so
yqm@unbuntu:~/Desktop/JNIDemo$ ll
总用量 36
drwxrwxr-x 2 yqm yqm 4096  57 10:20 ./
drwxr-xr-x 9 yqm yqm 4096  57 09:13 ../
-rw-rw-r-- 1 yqm yqm  441  57 09:14 HelloJNI.class
-rw-rw-rw- 1 yqm yqm  265  57 10:12 HelloJNI.cpp
-rw-rw-r-- 1 yqm yqm  372  57 09:14 HelloJNI.h
-rw-rw-rw- 1 yqm yqm  364  57 10:11 HelloJNI.java
-rwxrwxr-x 1 yqm yqm 8594  57 10:20 libhello_jni.so*
yqm@unbuntu:~/Desktop/JNIDemo$ 

6. Run

Use the command java -Djava.library.path=<LIBDIR> <ProgramName>to run the program. Among them, you <LIBDIR>need to use the path where the .so generated above is stored, and <ProgramName>you need to replace it with the name of the program you are running. Operation demonstration on linux system:

yqm@unbuntu:~/Desktop/JNIDemo$ java -Djava.library.path=. HelloJNI
From HelloJNI.cpp :Hello world !
yqm@unbuntu:~/Desktop/JNIDemo$ 

3. Summary

The above shows the general steps of using JNI through a simple example. In a Java program, we only need to define the Native function declaration and then use it. The only thing to note is that we need to load the JNI library before using it. In C and C++ programs, we only need to introduce automatically generated header files, implement the functions declared in the header files that correspond to the Java programs, and then compile and generate dynamic libraries.

Fourth, the description

1. g++Parameter description

1) -shared: Specify to generate a dynamic link library
2) -fPIC: The compiler outputs position-independent object code. It is suitable for dynamic linking
3) -I <dir>: When you use #include "file", gcc/g++ will first start in the current The directory looks for the file you have specified. If it is not found, it will look in the default header file directory. If you use -I to specify a directory, it will first look in the directory you specified, and then look in the usual order. . Above we used two -I parameters to specify two directories successively, which respectively contain the jni.h header file and the jni_md.h header file.
4) -o <outputFileName>: Specify the target name. By default, the file name compiled by gcc is a.out. It should be noted that on the Linux system, the name we specify here must be prefixed with lib and suffixed with .so. When loading the JNI library in a Java program, there is no need to specify the prefix and suffix.

2. java -Djava.library.path=<libpath>Description

We need to pass -Djava.library.path=<libpath>parameters to display the location of the dynamic library contained in the specified program.

For reference only, corrections are welcome.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325818984&siteId=291194637