-
写一段调用native方法的java代码。
package coroutinesLearning.jni; public class HelloWorld { // 声明一个native方法 public native void sayHello(); public static void main(String[] args) { new HelloWorld().sayHello(); } } -
使用javac生成一份头文件。
#/path/to/HelloWorld.java换成HelloWorld.java文件的相对路径或绝对路径 javac -h . /path/to/HelloWorld.java之后就能得到一个文件
coroutinesLearning_jni_HelloWorld.h,这名字是按照包名_类名.h格式得到的。/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class coroutinesLearning_jni_HelloWorld */ /*注释1*/ #ifndef _Included_coroutinesLearning_jni_HelloWorld #define _Included_coroutinesLearning_jni_HelloWorld /*注释2*/ #ifdef __cplusplus extern "C" {//C模式的开始 #endif /* * Class: coroutinesLearning_jni_HelloWorld * Method: sayHello * Signature: ()V */ /*注释3*/ JNIEXPORT void JNICALL Java_coroutinesLearning_jni_HelloWorld_sayHello (JNIEnv *, jobject); #ifdef __cplusplus }//C模式的结束 #endif #endif-
注释1
如果没定义_Included_coroutinesLearning_jni_HelloWorld,就定义_Included_coroutinesLearning_jni_HelloWorld,这是为了避免头文件被多次include,导致_Included_coroutinesLearning_jni_HelloWorld被重复定义。
-
注释2
这段代码的意识是告诉编译器,如果该头文件被C++文件include,则闭包部分(注释里用标注C模式的地方)按照C语言的规则来进行编译,这导致C模式下的代码实现不支持函数重载了,具体可看链接stackoverflow.com/a/3789553/1…
-
注释3
方法声明,不需要太关注JNIEXPORT和JNICALL两个符号,它两是定义在jni.h头文件的两个宏(标识符)。
-
-
实现native方法。
创建HelloWorld.c文件。
#include <jni.h> #include <stdio.h> #include "coroutinesLearning_jni_HelloWorld.h" JNIEXPORT void JNICALL Java_coroutinesLearning_jni_HelloWorld_sayHello(JNIEnv *env,jobject obj){ printf("Hello from C!\n"); } -
编译C文件生成so文件。
gcc -shared -o libhello.so -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin HelloWorld.c需要注意的是下述参数在可能在不同系统下会有变化,我的是macOS系统。
-I${JAVA_HOME}/include/darwin -
加载so库。
在原来的HelloWorld.java文件里新增一段加载so库的代码
package coroutinesLearning.jni; public class HelloWorld { static { //加载名为 "libhello" 的本地库 //这里放so文件的相对或绝对路径 System.load("/XXX/src/main/java/coroutinesLearning/jni/libhello.so"); } // 声明一个native方法 public native void sayHello(); public static void main(String[] args) { new HelloWorld().sayHello(); } } -
运行。