出于效率的问题,很多情况下,我们需要在上层的Java代码中调用底层 C或C++实现,这时jni就可以大显身手了。jni(Java Native Interface)允许Java代码和其他语言写的代码进行交互,使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样 做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。
使用JNI编程的步骤
- 在Java代码中使用native关键字声明一个本地方法
- 运行javah,获得包含该方法声明的C语言头文件(使用jni编程中的C函数名通常是相关于Java方法有一定的命名规则的,稍后会介绍,我们使用javah来帮助我们获得该方法名)
- 用C语言或C++实现我们所需要的功能
- 生成共享库文件,共享库文件可以是windows风格的.dll文件,也可以是UNIX风格的.so文件
- 为了确保虚拟机在第一次使用该类之前就会装载这个库,使用静态初始化块来加载
关于javah:在命令窗口中运行javah -h 命令我们可以看到javah的所有选项,这里简单介绍一下:
- -classpath,用于装入类的路径
- -d,输出目录
- -o,输出文件, -d和-o只能使用其中之一
- -jni,生成jni样式的头文件(默认)
编写第一个JNI程序
看到了上面的步骤我们来亲自实践一下,利用jni编写一个简单的hello world程序。
1.首先,我们用Java代码编写一个本地方法hello:
package com.example.jnitest;
public class JniTest {
public static native void hello();
}
2.接下来我们利用javah生成头文件,需要注意的是我们应该首先编译该工程得到.class文件。然后我们运行命令行来到工程目录/bin目录 下,输入命令 javah -classpath . com.example.jnitest.JniTest 得到头文件,如图:
得到头文件的代码如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnitest_JniTest */
#ifndef _Included_com_example_jnitest_JniTest
#define _Included_com_example_jnitest_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jnitest_JniTest
*