JNI示例
一、JNI简介
JNI:Java Native Interface,是Java语言提供的一种通用接口,用于Java代码与本地化代码的交互。所谓本地化代码是指直接编译成的与机器相关的二进制代码,而非Java字节码之类的中间代码。Windows下面的可执行文件,DLL等,Linux下面的可执行文件和SO文件等,都是二进制代码。JNI允许Java语言编写的程序与其他语言编写的程序库(DLL, SO)或可执行文件进行互操作,包括汇编、C、C++。JNI产生的原因在于以下几种需求:
(1). 你的应用程序需要使用系统相关的功能,而Java代码不支持或是难以办到。这个比较典型的是实现托盘图标,有几种现成的方案都是用的JNI做的,名字好像是叫做TrayIcon和StayOnTop。当然啦,如果是用的Java1.6,那就要另当别论了。
(2). 已有其他语言写好的类库或程序,希望Java程序可以使用它们。
(3). 出于更高的性能要求,希望使用汇编或是C/C++语言来实现部分功能。
其他的理论的东西就不多说了,JNI Tutorial讲得很清楚。强烈建议阅读。
二、JNI的开发步骤
这里以使用C++编写本地化方法实现为例,开发一个使用JNI的Demo程序,具体步骤如下所示:
(1). 编写带有native方法的java类
(2). 使用javac命令编译所编写的java类
(3). 使用javah命令处理类文件,生成C/C++头文件
(4). 使用C/C++实现本地方法
(5). 将C/C++编写的文件生成动态连接库
三、下面我们开始编写HelloWorld程序,由于涉及到要编写c/c++代码因此我们会在开发中使用Microsoft VC++工具。
1.编写java代码
在c盘根目录下新建java文件,内容如下:
class HelloWorld
{
public native void displayHelloWorld();
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}
注意System.loadLibrary("hello")这句代码,它是在静态初始化块中定义的,系统用来装载hello共享库,这就是我们在后面生成的hello.dll(如果在其他的操作系统可能是其他的形式,比如hello.so)
2. 编译java代码
javac HelloWorld.java 生成HelloWorld.class文件
3. 创建.h文件
javah HelloWorld
4. 编写本地实现代码
首先:打开VC++6.0,新建->工程 -> win32 Dynamic-Link Library ,名字随便取,在向导中选择空工程。
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}
保存编译,会发生错误:
a. 缺少jni.h。 jni.h通常在 jdk/include/, 可以先拷贝到VC安装目录下的include目录下。一劳永逸,以后可以方便使用JNI技术。
b. 缺少jni_md.h。在jdk\include\win32里找到jni_md.h,复制到c++工程下。
编译后有可能会提示叫指定可执行文件,选中Debag文件夹下的一个.exe文件就行了(原理不懂 =,=)。这样在c++工程下的debug文件夹下会有产生的.dll文件。复制到
C盘根目录,然后在命令行输入
java HelloWorld
就可以看到结果了。
前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。