技术简介

JNI,全称java native

interface,是java语言与其他类型语言交互的接口。下图是Sun站点上对JNI的基本结构的描述。JNI是Java语言的本地编程接口,是J2SDK的一部分。在java程序中,我们可以通过JNI实现一些用java语言不便实现的功能。通常有以下几种情况我们需要使用JNI来实现。 ·标准的java类库没有提供你的应用程序所需要的功能,通常这些功能是平台相关的 ·你希望使用一些已经有的类库或者应用程序,而他们并非用java语言编写的 ·程序的某些部分对速度要求比较苛刻,选择用汇编或者c语言来实现并在java语言中调用他们

Java中调用C/C++方法:

1、Native Method Declaration(原生函数声明)

原生函数声明是Java虚拟机与原生函数之间的桥梁。同样可以这样理解,它是Java虚拟机与本地库文件之间的接口。在具体运作上,它与普通的Java函数声明没有大的区别,除了要在函数声明前添加native关键字。函数声明的参数表应为Java的内部类型,有相应的JNI函数完成Java与其他不同语言之间的数据类型转换。

示例:

native
byte[] loadFile(String name);

2、Load the Library(装载原生函数库)

原生函数库文件包含了原生函数的代码实现,

通过调用System.loadLibrary进行装载.通常把它放置在静态初始化块中,以保证每个类只初始化一次,当然这也可以在别的地方.需要注意的是,你需要配置系统的环境以保证在运行时可以找到要装载的库文件.

示例:

static
{
System.loadLibrary("nativelib");
}

3、Complile the Program(编译程序)

调用javac编译java源文件.

示例:

javac
test.java

4、Generate the Header File

调用javah生成C/C++需要的头文件.生成头文件主要内容为C/C++语言的原生函数声明,它是Java语言与C/C++语言之间的接口.生成的原生函数声明来自Java中的原生函数声明,但有所不同.新的函数声明函数名字以及参数名字,均依照jni内部规则生成.需要注意的是:参数表的第一个总会是JNIEnv

*,虚拟机环境信息指针;第二个参数依据Java中原生函数声明不同而不同,静态函数为jclass,非静态函数为jobject.

示例:

javah
test

5、Implement the Native Method(实现原生方法)

包含生成的原生函数头文件和jni.h,编写原生函数的实现.原生函数内容主要为C/C++语言编写的平台相关代码,同时涉及与Java虚拟机之间数据的交换.JNI提供了相应的C/C++语言实现的转换函数,通过传入JNIEnv

*env给转换函数可以完成数据转换.详情见jni.h

6、Compile the Dynamic or Shared Object Library

编译C/C++程序,生成动态链接库,具体操作如下图所示

7、Run the Example

执行Java程序.需要注意,需要保证编译产生的动态链接库能够被正确装载.下图是不同操作系统下,指定当前目录为库文件目录的示例.如果指定为你它路径可仿此例.

参考文档: j2se1_42_jni.chm JDK1.42的jni规范

JAVA程序

Java本地接接口(JNI)

(1)安装JAVA

进行环境变量设置

新建变量path

变量值%path%;c:\JDK\bin

新建变量classpath

变量值.;c:\JDK\tools.jar (”.”和”

c:\JDK\tools.jar”)

简单例子

public class Example
{
public static void main(String args[])
{
System.out.println("hello
java!");
}
}

正常运行

开始编写HelloWorld程序,由于涉及到要编写c/c++代码因此我们会在开发中使用Microsoft VC++工具。编写java代码,我们在硬盘上建立一个hello目录作为我们的工作目录,首先我们需要编写java代码,在java代码中声明native方法

class HelloWorld { public native void displayHelloWorld(); //一个外部实现的方法
static { System.loadLibrary("hello"); //声明所调用的库名称hello.dll

} public static void main(String[] args) { new HelloWorld().displayHelloWorld(); } } 关键字native,表明这个方法使用java以外的语言实现。方法不包括实现,因为我们要用c/c++语言实现它。System.loadLibrary("hello"),它是在静态初始化块中定义的,系统用来装载hello共享库,这就是我们在后面生成的hello.dll(如果在其他的操作系统可能是其他的形式,比如hello.so)

编译java代码

生成HelloWorld.class

javac HelloWorld.java 生成HelloWorld.class文件 创建.h文件 这一步中我们要使用javah命令生成.h文件

生成HelloWorld.h

这个文件要在后面的c/c++代码中用到,我们运行 javah HelloWorld。这样我们可以看到在相同目录下生成了一个HelloWorld.h文件,文件内容如下 在此我们不对他进行太多的解释。 #include  #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif 编写本地实现代码 在这部分我们要用C/C++语言实现java中定义的方法,我们在VC++中新建一个Project,然后创建一个Hello.cpp文件,内容如下 #include  #include "HelloWorld.h" #include  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文件。

安装VC++6.0

新建一个工程!工程名称为HelloWorld(将生成HelloWorld.dll文件)

选择Win32 Dynamic-Link Library

创建一个空工程

在工具—>选项—>目录

添加C:\JDK\INCLUDE和C:\JDK\INCLUDE\WIN32在这些目录文件夹中包含JNI所需的头文件

在工作区中添加文件到目录下!如下图

Hello.cpp放置在source Files(源文件)里面

HelloWorld.h jni.h放置在Header

Files(头文件) 里面

再编译

组建生成dll文件!

运行java程序 把上面生成的hello.dll文件复制到我们的工