JNI简介

JNI 全称为 Java Native Interface,Java 本地接口,是 Java 调用 Native 语言的一种特性。通过 JNI 可以使得 Java 与 C/C++ 机型交互,即可以在 Java 代码中调用 C/C++ 等语言的代码或者在 C/C++ 代码中调用 Java 代码。由于 JNI 是 JVM 规范的一部分,因此可以将我们写的 JNI 的程序在任何实现了 JNI 规范的 Java 虚拟机中运行。同时,这个特性使我们可以复用以前用 C/C++ 写的大量代码。JNI 是一种在 Java 虚拟机机制下的执行代码的标准机制。

JNI HelloWord

  1. 新建一个Java项目来看看Linux下JNI调用_java


  2. 编写代码
 public class JNIDemo {
     public native  int add(int a,int b);
     public native void sayHello();
 
 }
 public class JNIMain {
     public static void main(String[] args) {
         String strLibPath = "/home/HouXinLin/projects/c/jnidemo/hello.so";
         System.load(strLibPath);
 
         JNIDemo jniDemo = new JNIDemo();
 
         System.out.println(jniDemo.add(1,2));
 
         jniDemo.sayHello();
 
     }
 }

  1. 生成头文件

    然后通过JDK工具javah生成JNIDemo类所需的头文件,javah 在JAVA_HOME\bin中。

    进入项目src路径

来看看Linux下JNI调用_java_02    

执行以下命令,最后面的包名根据自己的来换。

 javah -classpath . -jni -encoding UTF-8 com.company.JNIDemo

成功的话会在src目录下生成一个com_company_JNIDemo.h文件,内容如下。

 /* DO NOT EDIT THIS FILE - it is machine generated */
 #include <jni.h>
 /* Header for class com_company_JNIDemo */
 
 #ifndef _Included_com_company_JNIDemo
 #define _Included_com_company_JNIDemo
 #ifdef __cplusplus
 extern "C" {
 #endif
 /*
  * Class:     com_company_JNIDemo
  * Method:    add
  * Signature: (II)I
  */

 JNIEXPORT jint JNICALL Java_com_company_JNIDemo_add
   (JNIEnv *, jobject, jint, jint)
;
 
 /*
  * Class:     com_company_JNIDemo
  * Method:    sayHello
  * Signature: ()V
  */

 JNIEXPORT void JNICALL Java_com_company_JNIDemo_sayHello
   (JNIEnv *, jobject)
;
 
 #ifdef __cplusplus
 }
 #endif
 #endif
  1. 编写C++新建一个cpp文件,将上面生成的头文件复制到同级目录下。
 #include "com_company_JNIDemo.h"
 #include <stdio.h>
 
 JNIEXPORT void JNICALL Java_com_company_JNIDemo_sayHello(JNIEnv* env, jobject obj){
    printf("Hello,JNI!\n");
 };
 JNIEXPORT jint JNICALL Java_com_company_JNIDemo_add(JNIEnv * env, jobject obj, jint a, jint b){
   int rtn = (int)(a + b);
     return (jint)rtn;
 }
  1. 编译

    下面命令中的JDK路径需要换成自己的,成功之后会在同级目录生成一个demo.so文件。这个文件就是我们通过System.loadLibrary()要加载的,System.loadLibrary() 可以加载 dll(Windows)或 so(Linux)库。

  gcc demo.cpp -std=c++11 -fPIC -shared -I /home/HouXinLin/apps/java/jdk/jdk1.8.0_241/include -I /home/HouXinLin/apps/java/jdk/jdk1.8.0_241/include/linux -lm -o ./demo.so

运行

来看看Linux下JNI调用_java_03

Java 数据类型与 JNI 类型映射

Java 中的基本类型通过 javah 工具生成 .h 文件的时候,这些基本类型分别对应的类型是 jboolean,jbyte,jchar,jshort,jint,jlong,jfloat,jdouble。下面是详细的 Java 数据类型与 JNI 类型映射表:




booleanjbooleanC/C++8 位整型
bytejbyteC/C++ 带符号的 8 位整型
charjcharC/C++ 无符号的 16 位整型
shortjshortC/C++带符号的 16 位整型
intjintC/C++带符号的 32 位整型
longjlongC/C++带符号的 64 位整型
floatjfloatC/C++32 位浮点型
doublejdoubleC/C++64 位浮点型
Objectjobject任何 Java 对象,或者没有对应 java 类型的对象
ClassjclassClass 对象
Stringjstring字符串对象
Object[]jobjectArray任何对象的数组
boolean[]jbooleanArray布尔型数组
byte[]jbyteArray比特型数组
char[]jcharArray字符型数组
short[]jshortArray短整型数组
int[]jintArray整型数组
long[]jlongArray长整型数组
float[]jfloatArray浮点型数组
double[]jdoubleArray双浮点型数组