JNI概述
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。在java源码中,我们可以发现大量源码都是利用native方法来实现了。
当一个类被使用时,这个类的字节码就会加载到内存,这些字节码的入口就维持着这个类的一些标识符,包括方法代码存于何处,它有哪些参数,方法的描述符(public之类)等等。当一个类的方法描述符是native时,虚拟机会通过java.system.loadLibrary()加载相应的dll文件,并执行其中相应的方法。
JNI例子
那么如何编写自己的jni程序呢。
- 编写java代码
建立一个hello目录作为我们的工作目录,首先我们需要编写自己的java代码,在java代码中我们会声明native方法,代码如下所示
class HelloWorld
{
public native void displayHelloWorld();
static {
System.loadLibrary("hello");
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}
注意我们的displayHelloWorld()方法的声明,它有一个关键字native,表明这个方法使用java以外的语言实现。方法不包括实现,因为我们要用c/c++语言实现它。注意System.loadLibrary(“hello”)这句代码,它是在静态初始化块中定义的,系统用来装载hello共享库,这就是我们在后面生成的hello.dll(如果在其他的操作系统可能是其他的形式,比如hello.so)
- 编译java代码
javac HelloWorld.java 生成HelloWorld.class文件
- 创建.h文件
这一步中我们要使用javah命令生成.h文件,这个文件要在后面的c/c++代码中用到,我们运行
javah HelloWorld。这样我们可以看到在相同目录下生成了一个HelloWorld.h文件,文件内容如下
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
- Class: HelloWorld
- Method: displayHelloWorld
- Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
- 编写本地实现代码
在这部分我们要用C/C++语言实现java中定义的方法,我们在VC++中新建一个Project,然后创建一个HelloWorldImp.cpp文件,内容如下
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!/n");
return;
}
注意我们这里include了 jni.h和刚才得到的HelloWorld.h文件。因此你要在VC++里面设置好,jni.h在JAVA_HOME/include里面。编译通过后再生成hello.dll文件。
运行java程序
把上面生成的hello.dll文件复制到我们的工作目录,这时候我们的目录中包括HelloWorld.java,HelloWorld.class和hello.dll文件。运行java HelloWorld命令,则可在控制台看到Hello world 的输出了。