博客中提到的JNI均指Java Native Interface,Java本地接口。本地代碼均指C/C++代碼。
JNI簡介
JNI是Java平臺中的一個非常強大的特性段磨,通過JNI相關(guān)的接口,我們不僅可以在Java中調(diào)用本地代碼耗绿,也可以在本地代碼使用Java完成相關(guān)的操作苹支,并且不需要考慮操作系統(tǒng)之間的差異。那么JNI是如何消除操作系統(tǒng)之間的差異的呢误阻?首先债蜜,我們要理解兩個概念:Java平臺和主機環(huán)境。Java平臺是包含了Java虛擬機和Java API接口的編程環(huán)境堕绩,Java應(yīng)用程序會被編譯成與機器無關(guān)的二進制格式的類文件策幼,這些類文件能夠被Java虛擬機解析執(zhí)行。主機環(huán)境表示主機操作系統(tǒng)奴紧,本地庫和計算機指令集特姐。使用C/C++編寫的本地代碼會被編譯成與機器相關(guān)的二進制代碼并與本地庫鏈接起來。JRE(Java Runtime Environment)就是這樣的一個主機環(huán)境黍氮。Java應(yīng)用程序唐含、Java虛擬機、JNI沫浆、本地應(yīng)用程序或者本地代碼庫與主機環(huán)境之間的關(guān)系如下圖所示:
![](http://jianshu-lhz.qiniudn.com/jni.png?token=5QbuD1t1awvPXLZ2c1LroY2Gnpz_hCGAIwIwwR8H:Pb5GdOZL-BILEWQ3KxdaDuOAKJ8=:eyJTIjoiamlhbnNodS1saHoucWluaXVkbi5jb20vam5pLnBuZyIsIkUiOjEzOTYzMTkwNzV9)
Java應(yīng)用程序在Java虛擬機里解析執(zhí)行捷枯,Java虛擬機在主機環(huán)境里運行,并通過JNI接口與本地應(yīng)用程序或者代碼庫進行通信专执。
JNI啟示
需要強調(diào)的一點是淮捆,一旦使用JNI去編寫應(yīng)用程序就意味著你將失去Java平臺的兩個特性:
- Java應(yīng)用程序不再跨平臺運行。即便Java語言編寫的部分是跨平臺的本股,但是你仍然需要將本地代碼部分重新編譯成與平臺相關(guān)的代碼攀痊;
- 本地代碼并不是類型安全的語言,然而Java卻是拄显。因此苟径,如果本地代碼稍有差錯都回導(dǎo)致Java虛擬機崩潰」螅基于這一點棘街,在執(zhí)行JNI之前進行安全檢查是非常重要的一個步驟蟆盐。
什么情況下使用JNI
在《JNI啟示》小節(jié)中介紹了使用JNI的兩個劣勢,使用JNI之前通常需要考慮是否還有其它方式來完成Java與不同語言之間的交互遭殉,下面是三種常見的不使用JNI的方式:
- TCP連接或者其它IPC機制石挂;
- JDBC;
- Java IDL接口险污。
以上三種方式的共同特點是Java應(yīng)用程序與本地代碼是在不同進程中運行的誊稚,因此,本地代碼的錯誤并不會引起Java虛擬機的崩潰罗心。如果你需要Java應(yīng)用程序與在同一進程內(nèi)的本地代碼進行交互,那么JNI就派上用場了城瞎,比如以下幾種情況:
- Java API不支持與特定操作系統(tǒng)相關(guān)的特性渤闷;
- Java應(yīng)用程序想要訪問本地代碼庫,但是想減少進程間通信的開銷脖镀;
- 使用本地代碼實現(xiàn)對性能要求非常高的功能飒箭。