JNI
动态链接库文件:
- windows:.dll
- Linux:.so
Demo:
参考:https://blog.csdn.net/w1992wishes/article/details/80283403
1) 编写 Java 代码:
- vim DemoJni.java
- 使用 System.loadLibrary() 从 java.library.path 中加载对应的 dll 或 so 动态链接库
- 使用 native 关键字,声明对应的 native 方法 ```java package cn.demojie;
public class DemoJni { static { try { // 调用动态链接库 System.loadLibrary(“sayHello”); } catch (Exception e) { System.err.println(“load native library [sayHello] failed.”); } System.out.println(“load native library [sayHello] succeed.”); } // native关键字声明本地方法 public native static String sayHello(String name); public static void main(String[] args) { System.out.println(“Hello “ + sayHello(“Dean.”)); } }
**2) javac 编译:**
```bash
javac -d . -encoding UTF-8 DemoJni.java
- -d:直接在指定路径生成对应的包路径
3) 生成 c 的头文件 .h:
javah -d jnilib -jni cn.demojie.DemoJni
- -d:指定生成路径
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_demojie_DemoJni */
#ifndef _Included_cn_demojie_DemoJni
#define _Included_cn_demojie_DemoJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: cn_demojie_DemoJni
* Method: sayHello
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_cn_demojie_DemoJni_sayHello
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
4) 进入 jnilib 目录:
cd jnilib
5) 创建 c 源文件:
JNIEXPORT jstring JNICALL Java_cn_demojie_DemoJni_sayHello (JNIEnv *env, jclass jc, jstring name) { return name; }
**6) 编译 c 文件:**
- JAVA_HOME 需要指向 JDK 的安装路径,如果已经设置了环境变量,则可以自动获取
- export JAVA_HOME=xxxx
```bash
gcc -D_REENTRANT -fPIC -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -c sayHello.c
- 头文件中程序依赖了 jni.h,而这个头文件是存在于 JDK 的 include 中的
7) 生成动态链接库文件(.so):
gcc -shared sayHello.o -o libsayHello.so
8) 返回上层目录:
cd ..
9) 运行 java 程序:
java -Djava.library.path=jnilib cn.demojie.DemoJni
- java.library.path:指定动态链接库文件所在的路径
整个文件:
之后只需要这个动态链接文件 libsayHello.so,Java 程序就可以调用对应的 native 方法了。
缺点:
JNI 只能调用符合 JVM 规范的动态库,而且对应的 c 程序需要引用 jni.h。对于大多数系统的动态链接库,只能通过编写一个中间的动态链接库进行间接调用,比较麻烦。