目录
- 安装JDK及配置环境变量
- 写Java代码
- 生成头文件
- 实现本地方法
- 编译本地代码
- 运行 Java 程序
- 总结步骤
安装JDK及配置环境变量
参考:MAC系统安装JDK1.8及环境变量配置
写Java代码
// 文件名:Calculator.java
public class Calculator {// 声明本地方法public native int add(int a, int b);// 加载动态链接库static {try {System.load("/Users/zhanghao/Downloads/java_excise/jni示例/libcalculator.so");//这里必须使用绝对路径} catch (UnsatisfiedLinkError e) {System.err.println("Failed to load library: " + e.getMessage());}}public static void main(String[] args) {System.out.println("Ready to add!");Calculator calculator = new Calculator();int result = calculator.add(5, 3);System.out.println("Result: " + result);}
}
在这段 Java 代码中,我们声明了一个本地方法 add,它将在后面的 C 代码中实现。
我们还使用 System.loadLibrary 方法加载动态链接库libcalculator.so,它也将由后面的.c和.h文件生成。
注意到"/Users/zhanghao/Downloads/java_excise/jni示例/libcalculator.so"这个路径,他也是当前文件Calculator.java所在的路径。
生成头文件
在终端中,切换到包含 Java 代码的目录,并运行以下命令:
javac -h . Calculator.java
//新版JDK不支持javah指令,只能用javac -h
这步将生成2个文件,第1个是名叫 Calculator.h 的头文件,它包含了我们需要在 C 代码中实现的本地方法的声明。第2个是叫Calculator.class文件,它是Java 编译后的字节码文件,用于最后通过Java指令执行。如下图:
其中,Calculator.h内容如下(第一行已经写明这是机器生成的文件,不需要改它):
实现本地方法
打开生成的头文件 Calculator.h看一下,并创建一个Calculator.c文件,在里面实现 Java_Calculator_add 方法。
// 文件名:Calculator.c
#include <stdio.h>
#include "Calculator.h"JNIEXPORT jint JNICALL Java_Calculator_add(JNIEnv *env, jobject obj, jint a, jint b) {printf("in C program!\n");return a + b;
}
在这个 C 文件中,我们先是加了打印,然后实现了头文件中声明的本地方法 Java_Calculator_add,它将两个整数相加并返回结果。
编译本地代码
在终端中,使用 GCC 编译器,运行以下命令来编译本地代码,并生成动态链接库:
gcc -c -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" Calculator.c
gcc -shared -o libcalculator.so Calculator.o
这将生成名为 libcalculator.so 的动态链接库文件,其中包含了我们的本地方法的实现。
解释一下这2条指令:
-c: 这个选项告诉编译器只进行编译,而不进行链接。这意味着它将产生一个目标文件而不是可执行文件。
-fPIC: 这个选项告诉编译器生成位置独立的代码(pasition independent code,这对于动态链接库(Shared Object)非常重要。
-I"xxx": 这个选项告诉编译器去 xxx 目录下查找头文件。在这个目录下,通常会有 jni.h , jni_md.h等 JNI 相关的头文件。
-shared表示生成一个共享库(动态库)文件。该条指令表示将 Calculator.o 这个目标文件编译并链接成一个名为 libcalculator.so 的共享库。
如果第一条指令失败,需要回头检查JDK的配置,通过echo $JAVA_HOME来查看Java的环境变量,如下图:
运行 Java 程序
在终端中,运行以下命令来执行 Java 程序:
java Calculator
输出结果是:
通过这个示例,我们可以了解到如何使用 JNI 来调用本地 C 代码,并将其集成到 Java 程序中。
总结步骤
共有下面几条指令:
//创建并撰写Calculator.java
javac -h . Calculator.java
//创建并撰写Calculator.c
gcc -c -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" Calculator.c
gcc -shared -o libcalculator.so Calculator.o
java Calculator
共有下面6个文件
$ls
Calculator.c Calculator.h Calculator.o
Calculator.class Calculator.java libcalculator.so
其中只有.java和.c文件需要手动写,其余都是自动生成的。