JNI 是 Java本地接口 (Java Native Interface),是为了方便 Java 调用 C 、C++等本地代码而封装的一层接口。
学习下 Java 开发环境下 jni 的使用。
新建一个类,就用它来测试。
package com.lah.studyjni;
public class HelloJni {
static {
System.loadLibrary("HelloJni");//注释1
}
public native void setParam(String param);//注释2
public native String getJniParam();//注释3
public static void main(String[] args) {
HelloJni helloJni = new HelloJni();
helloJni.setParam("test");//注释4
System.out.println("JniParam:" + helloJni.getJniParam());//注释5
}
}
注释1 处加载 HelloJni 库。
注释2、注释3 处声明 native 方法。
注释4、注释5 处调用 native 方法。
在 IntelliJ IDEA 的 Terminal 栏执行 javac com/lah/studyjni/HelloJni.java
生成 HelloJni.class
。
留意下,javac 命令要跟着完整路径,我把生成的 class 文件和 java 文件放在同级目录。
在 IntelliJ IDEA 的 Terminal 栏执行 javah -d ./com/lah/studyjni/ com.lah.studyjni.HelloJni
生成 com_lah_studyjni_HelloJni.h
文件。
留意下, -d
是指定生成文件的目录,我这里指定到 HelloJni.java 同级目录。
com_lah_studyjni_HelloJni.h
文件完整代码,
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_lah_studyjni_HelloJni */
#ifndef _Included_com_lah_studyjni_HelloJni
#define _Included_com_lah_studyjni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lah_studyjni_HelloJni
* Method: setParam
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_lah_studyjni_HelloJni_setParam
(JNIEnv *, jobject, jstring);
/*
* Class: com_lah_studyjni_HelloJni
* Method: getJniParam
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lah_studyjni_HelloJni_getJniParam
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
函数名的格式为: Java_包名_类名_方法名。
如 Java_com_lah_studyjni_HelloJni_setParam ,com_lah_studyjni 是包名,HelloJni 是类名,setParam 是方法名 。
编写 HelloJni.c 文件,实现 com_lah_studyjni_HelloJni.h
文件中的方法。
#include
#include
#include "com_lah_studyjni_HelloJni.h"
/*extern "C" */JNIEXPORT void JNICALL
Java_com_lah_studyjni_HelloJni_setParam(
JNIEnv *env,
jobject thisObj,
jstring param) {
printf("invoke Java_com_lah_studyjni_HelloJni_setParam");
return;
}
/*extern "C" */JNIEXPORT jstring JNICALL
Java_com_lah_studyjni_HelloJni_getJniParam(
JNIEnv *env,
jobject thisObj) {
char* str = "Hello World from c";
return (**env).NewStringUTF(env, str);
}
我用的 Windows 。
到 https://nuwen.net/mingw.html 下载安装包,
然后安装,指定解压路径,路径自己选,
还需要将安装目录下 bin 文件夹的路径(我的是 D:\MinGW\MinGW\bin)加入到系统环境变量 path 中。
具体方法是:
依次选择 桌面→ 计算机 → 右键选择属性 → 高级系统设置 → 环境变量 → 系统变量 ,
在 path 变量中加入 D:\MinGW\MinGW\bin;
(注意,符号要用英文的)。
安装成功后到控制台执行 gcc -v 查看是否安装成功。
至此,安装完成。
安装成功后,可以直接在控制台执行 gcc 语句,但是在 IntelliJ IDEA 中执行不了,提示找不到该语句。需要重启电脑才可以在 IntelliJ IDEA中执行 gcc 语句。
dll 用于 Windows 开发环境。
预先在工程目录新建一个 lib 目录存放 dll 文件,这个目录(D:\JetBrains_java_project\src\lib\)后面用到。
在命令行执行如下语句,
gcc --shared -I “D:\Android Studio\jre\include” -I “D:\Android Studio\jre\include\win32” -fPIC D:\JetBrains_java_project\src\com\lah\studyjni\HelloJni.c -o D:\JetBrains_java_project\src\lib\HelloJni.dll
参数说明:
gcc --shared -I
(大写的 i): --shared
用于生成共享目标文件;-I
(大写的 i)用于指定头文件路径
D:\Android Studio\jre\include :JDK 路径下 jni.h 文件的路径,不带这个参数会报错 fatal error: jni.h: No such file or directory
;
D:\Android Studio\jre\include\win32 :JDK 路径下 jni_md.h 文件的路径,不带这个参数会报错 fatal error: jni_md.h: No such file or directory
。
-fPIC :暂未知。
-o :指定输出文件。
D:\JetBrains_java_project\src\com\lah\studyjni\HelloJni.c : 我的工程里,c文件的路径 。
D:\JetBrains_java_project\src\lib\HelloJni.dll :生成的 dll 的路径和名称。(需要确保该目录存在)
这样,在 D:\JetBrains_java_project\src\lib\ 目录下就生成 HelloJni.dll 了。
在工程中,选择 Run --> Edit Configuration ,VM option 选项写入 -Djava.library.path=dll文件所在的文件夹路径
确认,保存,运行。
运行结果,
JniParam:Hello World from c
invoke Java_com_lah_studyjni_HelloJni_setParam
符合预期,成功了。