创建一个java类
我们从一个Java类开始我们程序,我们需要定义一个名为Hello World的类,这个类需要在名为HelloWorld.java的Java源码文件,主要包含三个部分:
- 一个原生函数print的生命,由原生代码实现.
- 一个主函数,作为Java程序入口, 并在主函数中调用print.
- 一个静态代码块,用来加载动态链接库.
class HelloWorld {
static {
System.loadLibrary("HelloWorld");
}
private native void print();
public static void main(String[] args) {
new HelloWorld().print();
}
}
print函数声明中的native修饰符,这个修饰符标示该函数是使用其他语言实现, 编译器不会因为其没有在Java代码中找到实现而报错.
包含原生代码的动态链接库一定要在原生函数被调用之前加载.
编译HelloWorld类
javac HelloWorld.java
这个命令将会在当前目录生成HelloWorld.class文件.
创建Native方法头文件
接下来我们需要使用javah工具生成JNI风格的头文件了,之后我们需要在c文件中实现相关的原生方法,你可以执行一下命令:
javac -h jni HelloWorld.java
实现Native方法
javah生成的HelloWorld.h头文件清晰的罗列了native函数的函数原型,包括函数名,参数及返回值等,我们只需要按照这个函数原型实现其函数体就可以了.你可以使如下代实现HelloWorld.c
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <stdio.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject) {
printf("Hello JNI!\n");
}
#ifdef __cplusplus
}
#endif
#endif
编译C源码并创建一个Native库
gcc -I/usr/lib/jvm/java-17-openjdk-amd64/include -I/usr/lib/jvm/java-17-openjdk-amd64/include/linux HelloWorld.c -shared -o libHelloWorld.so
执行程序
java -Djava.library.path=./jni HelloWorld
正确的设置动态链接库的路径对于程序成功运行只管重要,在加载时候需要将动态链接库所对应的目录加入系统LD_LIBRARY_PATH环境变量,或者在执行java命令的时候加入java.library.path选项,制定库所在目录.