對于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函數表: