参考资料-韦东山老师第四期资料
主要参考视频讲解和相关文档,进行java的一个小的学习总结。本文讲解JNI的实现原理和代码实验。
整体流程如下:
下面用代码来实现下,由于我这边使用的windows的电脑,所以采用虚拟机的方式,安装ubuntu(需要安装java,参考网上其他教程即可)进行操作。
先实现一个java程序和一个c程序(命名随意)
JniDemo.java
public class JniDemo{
//静态代码块,在构造一个对象之前就会执行,并且只执行一次
static{
/*加载c库*/
System.loadLibrary("native");//libnative.so,到时有native.c生成
}
public native static void hello(); //native 表示所声明的函数是本地语言实现的即C语言
public static void main(String args[]){
/*调用函数*/
hello();
}
}
native.c,在这里实现java和c库的映射关系,c_hello与java中的hello
#include<stdio.h>
#include<jni.h>
#if 0//从思维导图中摘录下来
typedef struct {
char *name; /* Java里调用的函数名 */
char *signature; /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */
void *fnPtr; /* C语言实现的本地函数 */
} JNINativeMethod;
#endif
void c_hello()
{
printf("hello world \n");
}
static const JNINativeMethod methods[] = {
{"hello", "()V", (void *)c_hello}, //"()V "是怎么的来的?
};
//system.loadLibrary
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)//参考jni.pdf 117页,有示例用法
{
JNIEnv *env;
jclass cls;
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) { //获得运行环境
return JNI_ERR; /* JNI version not supported */
}
cls = (*env)->FindClass(env, "JniDemo"); //查找类JniDemo.java中的类名
if (cls == NULL) {
return JNI_ERR;
}
///*建立java和c的映射*/
if(((*env)->RegisterNatives(env,cls,methods,1))<0) //看思维导图,需要使用RegisterNatives方法,RegisterNatives方法是前面获得运行环境的方法,用法看jni.pdf 101页,methods数组进行java和c的函数的映射
return JNI_ERR;
return JNI_VERSION_1_4;
}
下面来编译下看:
//进入到相应目录下
javac JniDemo.java
gcc -shared -o libnative.so native.c //编译为动态链接库
//提示错误: fatal error: jni.h: No such file or directory
//找下看find -name jni.h
//./book/jdk1.6.0_45/include/jni.h,这个可能每个人不太一样
编译时包含下这个头文件需要-I加上
gcc -I/home/book/jdk1.6.0_45/include/jni.h -shared -o libnative.so native.c
/home/book/jdk1.6.0_45/include/jni.h:27:20: fatal error: jni_md.h: No such file or directory
继续搜索看下jni_md.h在哪个位置,包含这个头文件即可(/home/book/jdk1.6.0_45/include/linux)
最终的编译命令如下:
gcc -I/home/book/jdk1.6.0_45/include/ -I/home/book/jdk1.6.0_45/include/linux/ -fPIC -shared -o libnative.so native.c
( -fPIC 是编译时提示要加上)
ls查看下
JniDemo.class JniDemo.java libnative.so native.c
libnative.so 库已经生成
//然后执行下
java JniDemo
//会提示找不到库(Exception in thread "main" java.lang.UnsatisfiedLinkError: no native in java.library.path
),需要导出环境变量,库在当前路径下,之后执行就可以出现结果,java成功调用到了c语言中的c_hello()
export LD_LIBRARY_PATH =.
java JniDemo
hello world//成功执行