JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。
使用JNI可以使java代码调用本地的库文件(Windows: .dll Linux: .so)。下面以使用JNI调用本地生成的dll库文件为例说明JNI的用法。
首先在Eclipse中写好java文件(工程名为DemoJniTest):
package com.sj.myjni;
public class MyJni {
public native void display();
public native double sum(double x, double y);
static {
//不要添加后缀,其会自动识别,否则会报错(提示找不到文件,链接错误)
System.loadLibrary("mylib");
}
public static void main(String... args) {
MyJni myJni = new MyJni();
myJni.display();
double sum = myJni.sum(0.5f, 0.6);
System.out.println(sum);
}
}
然后在DemoJniTest 工程中的bin 文件夹下 使用 javah com.sj.myjni.MyJni 生成头文件,将此头文件拷入VC工程中。
VC下开发dll:
头文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_sj_myjni_MyJni */
#ifndef _Included_com_sj_myjni_MyJni
#define _Included_com_sj_myjni_MyJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_sj_myjni_MyJni
* Method: display
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_sj_myjni_MyJni_display
(JNIEnv *, jobject);
/*
* Class: com_sj_myjni_MyJni
* Method: sum
* Signature: (DD)D
*/
JNIEXPORT jdouble JNICALL Java_com_sj_myjni_MyJni_sum
(JNIEnv *, jobject, jdouble, jdouble);
#ifdef __cplusplus
}
#endif
#endif
C代码源文件:
#include "jni.h"
#include "com_sj_myjni_MyJni.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_com_sj_myjni_MyJni_display
(JNIEnv *, jobject)
{
printf("execute!");
return;
}
/*
* Class: com_sj_myjni_MyJni
* Method: sum
* Signature: (DD)D
*/
JNIEXPORT jdouble JNICALL Java_com_sj_myjni_MyJni_sum
(JNIEnv *, jobject, jdouble a, jdouble b)
{
return a + b;
}
生成dll 文件。将其拷贝到MyJni 工程根目录下(与SRC同目录)即可,编译,运行,OK!
注意:
1、生成的头文件要放到VC工程与源代码文件同一级目录下,否则提示找不到此头文件
2、编译VC工程发现提示找不到 "jni.h" 同文件,解决方法是将 JDK 安装目录下的 jni.h 等三个文件拷贝到 VC安装目录的Include 目录下
3、生成的dll 文件要拷贝到java 工程的根目录下,否则提示找不到库文件
4、loadLibrary(...) 库文件名不要添加后缀,其会自动识别,否则会报错(提示找不到文件,链接错误)
5、JNIEXPORT、 JNICALL 为JNI提供关键字,暂时不必理会。Native 方法的本地实现的 函数名的生成方法是 Java_包名_函数名。jdouble 是 java 数据类型和C数据类型的中转类型。