概述
JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与平台无关这一重大优点的不足,在JAVA实现跨平台的同时,也能与其它语言(如C、C++)的动态库进行交互,给其它语言发挥优势的机会。
有了JAVA标准平台的支持,使JNI模式更加易于实现和使用。在此总结了下面这个知识图:
实践
编写JNI接口类
public class HelloWorld {
static
{
/// 需要加载的动态库名称
System.loadLibrary("HelloWorld");
}
/// 使用关键字 “native” 定义接口方法
public native String GetHello();
public void DisplayHello()
{
String str_tmp = GetHello();
System.out.println("Class[HelloWorld]:" + str_tmp);
}
}
生成JNI接口文件
1、进入src目录下,编译JAVA类,
命令:
javac ./JinInterface/HelloWorld.java
在该HelloWorld.java所在目录下生成HelloWorld.class
2、使用javah生成头文件,
命令:
javah -jni JinInterface.HelloWorld
在当前目录下生成JinInterface_HelloWorld.h头文件,此文件供C、C++程序来引用并实现其中的函数
JinInterface_HelloWorld.h 文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class JinInterface_HelloWorld */
#ifndef _Included_JinInterface_HelloWorld
#define _Included_JinInterface_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JinInterface_HelloWorld
* Method: GetHello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_JinInterface_HelloWorld_GetHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
编译动态库
1、引用JNI头文件(JinInterface_HelloWorld.h),实现JNI头文件中的接口方法,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "JinInterface_HelloWorld.h"
JNIEXPORT jstring JNICALL Java_JinInterface_HelloWorld_GetHello
(JNIEnv *env, jobject)
{
char p_str[] = "Java_JinInterface_HelloWorld_GetHello : HelloWorld";
// 定义java String类 strClass
jclass strClass = (env)->FindClass("Ljava/lang/String;");
// 获取java String类方法String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
// 建立byte数组
jbyteArray bytes = (env)->NewByteArray((jsize)strlen(p_str));
// 将char* 转换为byte数组
(env)->SetByteArrayRegion(bytes, 0, (jsize)strlen(p_str), (jbyte*)p_str);
//设置String, 保存语言类型,用于byte数组转换至String时的参数
jstring encoding = (env)->NewStringUTF("GB2312");
//将byte数组转换为java String,并输出
return (jstring)(env)->NewObject(strClass, ctorID, bytes, encoding);
}
编译成功后,生成动态库。
JAVA 通过JNI调用动态库
import JinInterface.HelloWorld;
public class HelloWorldTest {
static HelloWorld m_hello_world = new HelloWorld();
public static void main(String[] args) {
// TODO Auto-generated method stub
m_hello_world.DisplayHello();
}
}
运行结果:Class[HelloWorld]:Java_JinInterface_HelloWorld_GetHello : HelloWorld
-------------------------------------------------------------------------------------------------------------------------------
注意事项:
1、动态库存放路径;目前使用的方法是,直接将动态库所在路径配置到环境变量PATH里面。
2、调用动态库时,需要注意JDK版本,如果编译出来的动态库是32位的,使用64位JDK无法正常调用。