JNI(Java Native Interface ),java本地接口,为了方便java代码调用C++/C代码.
Java本身的跨平台特性导致它和本地交互的能力不是特别强,一些和操作系统相关的特性Java没法完成.所以Java就提供了JNI接口历来调用C++/C编写的代码.
下面写一个demo,让大家体会体会(注:我用的是Linux系统):
- 新建一个文件夹jni2,在这里先写一个Java文件,命名为JniTest2.java,内容如下:
代码:
import java.lang.System:
public class Jnitest2{
static{
System.loadLibrary("jni-test");
}
public static void main(String[] args){
Jnitest2 jnitest2 = new Jnitest2();
System.out.println(jnitest2.get());
jnitest2.set("hello world");
}
public native String get();
public native void set(String str);
}
2. 回到命令窗口,切换到jni2文件夹,执行命令 javac Jnitest2.java, 生成Jnitest2.class 文件,再执行javah Jnitest2,生成Jnitest2.h头文件.(注意:生成的文件不会立即显示出来,需要重新打开jni2文件夹)
Jnitest2.h 代码内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Jnitest2 */
#ifndef _Included_Jnitest2
#define _Included_Jnitest2
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Jnitest2
* Method: get
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_Jnitest2_get
(JNIEnv *, jobject);
/*
* Class: Jnitest2
* Method: set
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_Jnitest2_set
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
3. 在jni2目录下接着创建一个cpp文件.文件名test2.cpp,
#include "Jnitest2.h"//这里因为生成的Jnitest2.h文件和test2.cpp文件放在了同一目录
//如果不是同一目录的话,需要把Jnitest2.h文件所在的完整路径写上去
#include <stdio.h>
JNIEXPORT jstring JNICALL Java_Jnitest2_get(JNIEnv *env,jobject thiz){
//对应java的get()方法
//这里的jstring 代表java方法里返回的是String对象
//至于写Java_Jnitest2_get的原因:Java_类名_方法名
printf("invoke get c++\n");
return env->NewStringUTF("Hello from JNI !");
}
JNIEXPORT void JNICALL Java_Jnitest2_set(JNIEnv *env,jobject thiz,jstring string){
//对应java的set方法
printf("invoke set from C++\n");
char* str = (char*)env->GetStringUTFChars(string ,NULL);
printf("%s\n",str);
env->ReleaseStringUTFChars(string,str);
}
4,接着需要把test2.cpp文件链接生成so库,
大家注意到,Jnitest2.h的头文件中有#include <jni.h>,而且jni.h也确实存在jdk的路径里面,
至于我写到linux这一层,是因为我在运行是它又提示我缺少jni_md.h文件,而这个文件恰好在linux文件夹中,所以我直接copy 了一份jni.h文件到linux文件夹中.
5,运行测试