JNI-Java Native Interface

Java提供了JNI机制,用来弥补与平台无关的特性,可以使用C/C++编写本地代码生成动态连接库交由Java调用。

首先创建一个NativeHelloWorld.java文件,包含以下内容;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//java本地方法要由native声明
public class NativeHelloWorld{
//使用静态加载块加载dll
static{
System.loadLibrary( " NativeHelloWorld " );
}
//native声明的start方法,交由c/c++实现,因此无需包含方法体;
native void start(String s);
public static void main(String[] args)
{
//实例化对象并调用start方法;
new NativeHelloWorld().start( " I am loaded by Native code of c++ " );
}
}
1
2
3
4
5
//打开cmd,执行javac命令
javac NativeHelloWorld.java
//当前目录将生成一个NativeHelloWorld.class,继续执行javah命令
javah NativeHelloWorld
//此时生成了一个名为NativeHelloWorld.h的c/c++头文件

NativeHelloWorld.h的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class NativeHelloWorld */

#ifndef _Included_NativeHelloWorld
#define _Included_NativeHelloWorld
#ifdef __cplusplus
extern " C " {
#endif
/*
* Class: NativeHelloWorld
* Method: start
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_NativeHelloWorld_start
(JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

生成头文件后,就是将该头文件运用到c/c++中并实现NativeHelloWorld.h里面的方法,最后编译成动态连接库dll放入NativeHelloWorld.class同路径下。

我这里使用的是vs2008,c++语言实现,选择新建项目->visual c++ win32->win32项目->程序设置中选择DLL->完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// NativeHelloWorld.cpp : 定义 DLL 应用程序的导出函数。
//
//jni.h、jni_md.h可在java安装目录中的include找到,复制到本项目文件夹中

//NativeHelloWorld.h则是刚刚由javah生成的,里面包含了要被java调用的本地函数的原型。

/*start方法的原型是:JNIEXPORT void JNICALL Java_NativeHelloWorld_start
(JNIEnv *, jobject, jstring);*/

#include " stdafx.h "
#include " jni.h "
#include " NativeHelloWorld.h "
#include <iostream>
using namespace std;
//JNIEnv *env指针包含一些对java数据类型以及c/c++数据类型转换操作的函数(函数在jni.h中有声明)
//jobiect这个我还没有具体了解
//jstring str是java在本地代码中String的数据类型,当返回一个jstring时相当于返回一个String
JNIEXPORT void JNICALL Java_NativeHelloWorld_start
(JNIEnv *env, jobject, jstring str){
//使用JNIEnv调用const char* GetStringUTFChars(jstring str, jboolean *isCopy)
//实现java数据类型到c++数据类型转换。
const char *p=env->;GetStringUTFChars(str,false);
char c[20];
cout<<"请输入字符(Enter):";
cin.getline(c,20);
cout<<"由JAVA传入的内容是:\n"
<<p
<<"\nAddress:"
<<&p
<<"\n用户输入的是:"<<c<<"\nAddress:"<<&c;
}

编译生成NativeHelloWorld.dll
把dll放入NativeHelloWorld.class相同目录下
在cmd中执行java NativeHelloWorld
看到程序运行如下:

1
2
3
4
5
6
7
F:\java>java NativeHelloWorld
请输入字符(Enter):Native Hello World
由JAVA传入的内容是:
I am loaded by Native code of c++
Address:009AFC9C
用户输入的是:Native Hello World
Address:009AFC80

JNI的简单运用如上!