一、什么是JNI?
JNI是 Java Native Interface的缩写,又叫Java本地方法/Java native方法。用于Java代码和其他语言写的代码进行交互。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境。
个人认为JNI可以理解为Java代码与已经编译好的工具库或者硬件系统的通道。当Java需要调用 C/C++或汇编语言编写的程序和库时,就要使用JNI。
但是,由于对应于某一平台的 JNI 本地代码调用通常不能移植到其他平台上,在 applet 中使用还可能引发安全异常。因此,从跨平台性考虑,在系统实现中一般要求尽可能少使用本地代码。如果必须要使用,要使本地方法尽量简单,独立。
需要注意的是,不是本地方法不是Java独有,很多编程语言也有本地方法。
二、如何使用
在Java中使用本地方法,用native来修饰,并且不能实现。具体例子,可以参考:JNI_百度百科
三、native方法与Java虚拟机
我们知道,JVM在执行Java程序时,会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁(来自《深入理解Java虚拟机》)。
虚拟机栈为虚拟机执行Java方法(也就是字节码)服务;本地方法栈为虚拟机使用的native方法服务。甚至有的虚拟机(譬如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一,即在调用普通方法时,创建java虚拟机栈帧,并压入栈中。当下个方法执行本地方法时,将切换到 本地方法栈,进行调用,运行在一起。虚拟机会保持 Java 栈不变,不再在线程的 Java 栈中压入新的帧,只是简单地动态连接并直接调用指定的本地方法。
本地方法栈也是线程私有,与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。(部分内容来自《深入理解Java虚拟机》)。
但并不是所有的JVM都支持本地方法。因为Java虚拟机规范并没有明确要求本地方法栈的使用语言、具体实现方式、数据结构等。如果JVM产品不打算支持native方法,也可以无需实现本地方法栈。
四、总结
JNI主要用于Java调用非Java语言的方法,或者调用操作系统或硬件的方法。在Java中使用时,用native修饰符修饰。在Java虚拟机管理的内存中,由本地方法栈为JNI服务,有些虚拟机直接将虚拟机栈和本地方法栈合二为一,不是所有的虚拟机都支持本地方法。