JnI

JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。[1]从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境。

SUN公司发布的Java 本地接口(JNI)提供了将Java与C/C++、汇编等本地代码集成的方案,该规范使得在 Java 虚拟机内运行的 Java 代码能够与其它编程语言互相操作,包括创建本地方法、更新Java对象、调用Java方法,引用 Java类,捕捉和抛出异常等,也允许 Java代码调用 C/C++或汇编语言编写的程序和库。作为一个标准程序接口,它没有对底层 Java虚拟机的实现施加任何限制,并具有以下特点:

二进制兼容。本地方法库与同一平台上所有Java 虚拟机之间实现二进制兼容,即对于给定平台开发人员只需要维护一种版本的本地方法库。

效率高。为了实现实时系统,JNI 在效率与虚拟机无关性之间进行了优化,以保障高效运行。

功能强。JNI 提供了大量的函数及接口让本地方法与Java 虚拟机内核相互操作,增强两者的功能。

本地代码与 Java 虚拟机之间是通过 JNI 函数实现相互操作的。JNI函数通过接口指针来获得,本地方法将 JNI 接口指针当作参数来接受。虚拟机保证在从相同的 Java 线程中对本地方法进行多次调用时,传递给本地方法的接口指针是相同的,本地方法被不同的 Java 线程调用时,它接受不同的 JNI接口指针。[2]

Java语言利用 JNI 接口访问的本地方法均需要包含在特定于平台的可执行文件中,例如,对32 位 Windows 操作系统而言,本地方法包含在动态链接库 DLL 中。由于对应于某一平台的 JNI 本地代码调用通常不能移植到其他平台上,在 applet 中使用还可能引发安全异常。因此,从跨平台性考虑,在系统实现中一般要求尽可能少使用本地代码。对于某些特殊应用(如硬件设备访问、网络底层协议访问等),必须执行本地调用,则要考虑以下准则:

将所有本地方法都封装在单个类中,这个类调用单个 DLL。对每种目标操作系统,用特定于平台的版本替换这个 DLL。这样可以将本地代码的影响减至最小,并有助于将以后所需的移植问题包含在内。

本地方法要简单。尽量使本地方法独立,将加载 DLL和应用程序的开销减到最小。如果需要其它运行时 DLL,必须随应用程序一起提供。以在 32 位 Windows 平台上采用 C/C++语言作为本地代码为例,采用此方案利用现有代码,需要根据现有代码的程序结构重新编写Java 代码,仅将 Java 不能实现的个别功能在Java 程序中声明为本地函数,用 Java h 命令生成相应的 C/C++头文件,再根据该头文件的格式编写相应的 C/C++实现代码,最后编译生成Java 代码可加载的 DLL 文件。

JDK1.0包含了一个本地方法接口,它允许JAVA程序调用C/C++写的程序,许多第三方的程序和JAVA类库。如:java.lang,java.io,java.net等都依赖于本地方法来访问底层系统环境的特征。不幸的是,JDK1.0中的本地方法有两个主要问题:

1、本地方法想访问C中的结构(structures)一样访问对象中的字段。尽管如此,JVM规范并没有定义对象怎么样在内存中实现。如果一个给定的JVM实现布局对象时,和本地方法假设的不一样,那你就不得不重新编写本地方法库。

2、因为本地方法可以保持对JVM中对象的直接指针,所以,JDK1.0中的本地方法采用了一种保守的GC策略。

JNI的诞生就是为了解决这两个问题,它可以被所有平台下的JVM支持:

(1)每一个JVM实现方案可以支持大量的本地代码。

(2)开发工具作者不必处理不同的本地方法接口。

(3)本地代码可以运行在不同的JVM上面。

JDK1.1中第一次支持JNI,但是,JDK1.1仍在使用老风格的本地代码来实现JAVA的API。这种情况在JDK1.2下被彻底改变成符合标准的写法。

你可能感兴趣的:(JnI)