JNI 主要是java和c++相互调用,java可以把效率低,耗时操作比较严重的逻辑放在c++里面。可以大大提升效率和节省资源。
下面是java调用的windows下的 c++的dll动态库,还有一种是标准c的linux的so动态库。工程结构图如下:
第一步:编写Java代码:
public class JniTest {
public native static String getString();
//【坑1】注意千万不要写成 public static native String getString()
//这样编译的dll动态库用不了,老是报莫名其妙的错
public static void main(String[] args) {
String result=getString();
System.out.println("test=java jni ="+result);
}
//加载动态库
static {
//正确导入方式
System.loadLibrary("JniDemo");
}
}
第二步:给java 调用类生成头文件
先复制工程目录src的路径
在打开cmd 利用javah生成头文件
//【坑2】java所在的类不能是GBK编码,不然报错
//【坑3】javah 后面是跟着java类的copy qualifed name
第三步:在visual studio 2013上新建空项目
a.将javah生成的头文件复制到vs工程目录下面,如下图所示:
b.vs引入头文件,如下图找到vs工程目录下的刚制过来的头文件,点击确定
c.vs引入刚才的头文件错误消除,如下图所示:
然后将jdk的两个.h头文件复制到vs工程目录下,并引入
C:\Program Files\Java\jdk1.8.0_152\include\jni.h
C:\Program Files\Java\jdk1.8.0_152\include\win32\jni_md.h
引入之后错误立马消失。
//打开javah生成java头文件的里面内容
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: jni_test_JniTest
* Method: getString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jni_1test_JniTest_getString
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
d.在vs工程源文件中新建JniTest.c文件,空白文件,并编写代码
#include "jni_test_JniTest.h"
//【坑4】方法和#include要有空行,不然报错
//下面这个方法是javah头文件中直接复制过来
JNIEXPORT jstring JNICALL Java_jni_1test_JniTest_getString
(JNIEnv *Env, jclass jclass){
//c或者c++实现函数
char *string = "what the fuck";
return (*Env)->NewStringUTF(Env, string);
};
第四步:vs生成dll动态库,设置步骤如下图所示:
最后点击vs的-》生成-》生成解决方案
第五步:将生成的dll动态库复制拷贝到java工程的更目录下面
第六步:运行java工程测试结果如下:(eclipse空间是GBK的,有乱码)
总结:总体来说java的jni交互流程还是有点复杂的,很容易出错。