通过JNI实现Java与C++的通信

  JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。使用Java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。下面我们实现一个简单的例子,通过JNI调用C++程序,输出“Hello world!”。   

1、创建一个Java类,定义一个本地方法(包名为util,类名为HelloWorld):

public native void helloWorld();

我们可以看到,这个方法只有声明,因为它是在本地被实现的。

2、在DOS窗口中进入文件src目录,输入命令“javah util.HelloWorld”,其中util为包名,HelloWorld为类名,这会在src目录下生成一个头文件util_HelloWorld.h,用记事本打开它我们可以看到:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class util_HelloWorld */

#ifndef _Included_util_HelloWorld
#define _Included_util_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     util_HelloWorld
 * Method:    helloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_util_HelloWorld_helloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

其中,
JNIEXPORT void JNICALL Java_util_HelloWorld_helloWorld
(JNIEnv , jobject); 是对本地方法的声明,*在C++程序中定义的方法必须与这个声明完全一致,否则可能导致无法加载本地方法。

3、现在我们开始编写C++本地代码,并生成DLL动态链接库文件。
如果使用VC6.0,则步骤为:文件——新建——Win32 Dynamic-Link Library,在这里我创建了一个名为util的工程,然后添加上面生成的头文件到该工程中,然后创建一个源文件(我在这里命名为MyDLL),include该头文件,并实现头文件中声明的函数:

#include<iostream.h>
#include"util_HelloWorld.h"
JNIEXPORT void JNICALL Java_util_HelloWorld_helloWorld(JNIEnv *, jobject);
{
cout<<"hello world!"<<endl;
}

由于util_HelloWorld.h中引入了jni.h,所以我们需要进入JDK安装目录,将include目录下的jni.h和include/win32目录下的jawt_md.h、jni_md.h复制到VC6.0目录下的include目录中。现在我们就可以构建该工程了,直接按F7,就会在该工程文件下的Debug目录中生成DLL文件(我目录下生成的文件名为util.dll)。

4、现在我们将上面得到的DLL文件导入到Java文件的根目录下,在Java程序中加载这个动态链接库文件,然后调用该本地方法:

public static void main(String[] args) {
        System.loadLibrary("util");
        new HelloWorld().helloWorld();
    }

便成功输出了“Hello World!”。

  注意,如果你是在64位的操作系统上安装的64位的JDK,那么在加载由VC6.0生成的DLL文件时会报错:Can’t load IA 32-bit .dll on a AMD 64-bit platform。由于VC6.0只能生成32位的DLL文件,我们就需要使用VS来生成64位的DLL文件。具体步骤为打开VS,这里我使用的是VS2012,点击文件——新建——项目——Visual C++——win32项目,输入项目名称,选择应用程序类型为DLL,点击完成,然后选择 生成——配置管理器,选择平台——新建——选择x64,按F7生成即可。(同样我们需要将jni.h、jawt_md.h、jni_md.h等头文件添加到VS目录下的VC/include中,且生成的DLL文件在项目文件下的x64/Debug中)。