对于Java程序员来说,Java语言的优点真的不用我多说了吧,大家都懂,能列出一堆来。但咱们也得承认,Java这玩意儿也有它的缺点,比如在性能和跟底层打交道的时候就有点捉急。所以Java搞了个本地接口,主要就是让Java程序能通过虚拟机跟原生代码互动,这就是我们常说的JNI(Java Native Interface)。简单来说,它能让在Java虚拟机里跑的Java代码和用其他语言(像C、C++或者汇编)写的应用或库互相配合。
JNI最大的好处是不影响Java虚拟机的底层实现。虚拟机厂商可以随便加对JNI的支持,而不用管虚拟机的其他部分。对程序员来说,只要写一个版本的本地应用或库,就能兼容所有支持JNI的Java虚拟机了。那为啥要跟原生代码交互?主要有以下几点:
一:提升程序性能
大家都知道,Java相对于C/C++、汇编这些语言来说更高级。这个高级其实就是帮程序员省了不少事儿,很多底层的东西都交给Java虚拟机去处理了。不过嘛,既然多了虚拟机这一层,性能上自然就比直接访问底层的原生语言差了一点点。
二:实现一些底层功能
虽然Java的标准类库和API很强大,能搞定大部分功能,但有些需要直接和底层硬件交互的功能,Java API里的类库确实搞不定。这时候就得靠JNI了。
三:和已有的原生程序集成
如果操作系统上已经有一些用C或者C++写的软件,想把它们和Java程序集成起来,JNI就能派上用场了。
接下来聊聊JNI的接口函数和指针。平台相关的代码是通过调用JNI函数来访问Java虚拟机功能的,而这些函数可以通过接口指针拿到。接口指针就是指针的指针,指向一个放满指针的数组,每个指针又指向一个接口函数。每个接口函数在数组里都有固定的位置。下图展示了接口指针的结构。
其实JNI接口的设计有点像C++的虚函数表或者COM接口。用接口表而不是硬编码函数表的好处就是可以把JNI的名字空间和平台相关代码分开。这样虚拟机就可以轻松提供多个版本的JNI函数表。比如说,虚拟机可以支持以下两个JNI函数表:
JNI最大的好处是不影响Java虚拟机的底层实现。虚拟机厂商可以随便加对JNI的支持,而不用管虚拟机的其他部分。对程序员来说,只要写一个版本的本地应用或库,就能兼容所有支持JNI的Java虚拟机了。那为啥要跟原生代码交互?主要有以下几点:
一:提升程序性能
大家都知道,Java相对于C/C++、汇编这些语言来说更高级。这个高级其实就是帮程序员省了不少事儿,很多底层的东西都交给Java虚拟机去处理了。不过嘛,既然多了虚拟机这一层,性能上自然就比直接访问底层的原生语言差了一点点。
二:实现一些底层功能
虽然Java的标准类库和API很强大,能搞定大部分功能,但有些需要直接和底层硬件交互的功能,Java API里的类库确实搞不定。这时候就得靠JNI了。
三:和已有的原生程序集成
如果操作系统上已经有一些用C或者C++写的软件,想把它们和Java程序集成起来,JNI就能派上用场了。
接下来聊聊JNI的接口函数和指针。平台相关的代码是通过调用JNI函数来访问Java虚拟机功能的,而这些函数可以通过接口指针拿到。接口指针就是指针的指针,指向一个放满指针的数组,每个指针又指向一个接口函数。每个接口函数在数组里都有固定的位置。下图展示了接口指针的结构。
其实JNI接口的设计有点像C++的虚函数表或者COM接口。用接口表而不是硬编码函数表的好处就是可以把JNI的名字空间和平台相关代码分开。这样虚拟机就可以轻松提供多个版本的JNI函数表。比如说,虚拟机可以支持以下两个JNI函数表: