在看 JDK 源码的时候,不停往方法调用链下走,会发现到了很多标注了 native 的方法的地方就停止了。
native 标注的方法是 Java 本地方法,这些方法可以由 C、C++实现。当程序无法完全用 Java 实现的时候,本地方法可以处理这种情况。
一个简单的例子,在 java 中调 C++ 程序实现两个整数的求和。简单起见,在 Linux 平台实现。
创建一个 Java 程序
1 | public class CalSum { |
编译 CalSum.java 并生成 CalSum.h 头文件
1 | javac CalSum.java |
执行完 javah 命令后,会在当前目录下生成一个 CalSum.h 头文件,文件内容如下:
1 | /* DO NOT EDIT THIS FILE - it is machine generated */ |
在当前目录下创建 CalSum.c 文件并用 C++ 实现求和功能
1 |
|
生成 libcalsum_c.so
gcc CalSum.c CalSum.h -I /opt/openjdk-8u262/include -I /opt/openjdk-8u262/include/linux -fPIC -shared -o libcalsum_c.so
:warning: 这里主要是注意需要在 jdk 安装路径下找到 jni.h 和 jni_md.h 两个头文件的路径,然后添加编译命令中。
运行 CalSum 程序得到 C++ 程序返回的结果
java CalSum
输出:
1 | ❯ java CalSum |
所有流程总结
- 创建带有 native 标识的方法,并从 Java 中调用它
- Java 编译器生成 .class 字节码文件
- C/C++ 生成链接库
- 运行程序,执行字节码
- 执行到loadLibary或load调用的时候,添加一个 .so文件到这个进程中
- 执行到native方法的时候,通过方法签名,在已打开的.so文件中进行搜索
- 如果链接库内有对应方法,就会被执行,否则程序崩溃
参考
参考: