Android JNI 學習(一):JNI 簡介

JNI 即 Java Native Interface 是 native 編程接口,它容許在Java虛擬機(VM)內運行Java代碼與其餘編程語言(主要是C和C++)編寫的應用程序和庫進行交互操做。html

JNI最重要的好處是它對底層Java VM的實現沒有任何限制。所以,Java VM供應商能夠添加對JNI的支持,而不會影響VM的其餘部分。程序員能夠編寫一個native應用程序或庫的版本,並指望它能夠與支持JNI的全部Java VM一塊兒使用。java

本文主要將從如下幾點講述JNI相關的內容,用於咱們瞭解JNI:android

概述、背景、目標、實現方式。程序員

1、JNI 概述

雖然您能夠徹底使用Java編寫應用程序,但有些狀況下Java自己並不能知足您的應用程序的需求。當應用程序沒法徹底用Java編寫時,程序員使用JNI編寫Java Native 方法來處理這些狀況。算法

如下示例說明什麼時候須要使用Java Native方法:編程

  • 標準Java類庫不支持應用程序所需的與平臺相關的功能。
  • 您已經有一個使用另外一種語言編寫的庫,並但願經過JNI使其能夠訪問Java代碼。
  • 您但願在較低級別的語言(如C/C++)中實現一小部分時間關鍵代碼。

經過JNI編程,您可使用Native方法:數組

  • 建立,檢查和更新Java對象(包括數組和字符串)。
  • 調用Java方法。
  • 捕獲並拋出異常。
  • 加載類並獲取類信息。
  • 執行運行時類型檢查。

2、JNI 產生的歷史背景

來自不一樣供應商的VM提供了不一樣的Native方法接口。這些不一樣的接口迫使程序員在給定平臺上生成,維護和分發多個版本的本機方法庫。oracle

咱們簡要介紹一些本機方法接口,例如:編程語言

  • JDK 1.0本機方法接口
  • Netscape的Java運行時接口
  • Microsoft的原始本機接口和Java / COM接口

一、JDK 1.0本機方法接口

JDK 1.0 附帶了Native方法接口。不幸的是,這個接口不適合其餘Java VM採用有兩個主要緣由。 ide

首先,本機代碼訪問Java對象中的字段做爲C結構的成員。可是,Java語言規沒有定義對象在內存中的佈局方式。若是Java VM在內存中以不一樣方式佈局對象,則程序員必須從新編譯本機方法庫。 

其次,JDK 1.0的本機方法接口依賴於保守的垃圾收集器。unhand例如,不受限制地使用宏使得必須保守地掃描本機堆棧。

二、Java運行時接口

Netscape提出了Java運行時接口(JRI),它是Java虛擬機中提供的服務的通用接口。JRI的設計考慮了可移植性 - 它對底層Java VM中的實現細節作了不多的假設。JRI解決了普遍的問題,包括本機方法,調試,反射,嵌入(調用)等。 

三、原始本機接口和Java / COM接口

Microsoft Java VM支持兩種本機方法接口。在低級別,它提供了有效的原始本機接口(RNI)。RNI提供了與JDK本機方法接口的高度源級向後兼容性,儘管它有一個主要區別。本機代碼必須使用RNI函數與垃圾收集器明確交互,而不是依賴於保守的垃圾收集。

在更高級別,Microsoft的Java / COM接口爲Java VM提供了與語言無關的標準二進制接口。Java代碼能夠像使用Java對象同樣使用COM對象。Java類也能夠做爲COM類公開給系統的其他部分。

3、JNI 產生的目標

咱們相信,統一且通過深思熟慮的標準接口爲每一個人提供如下好處:

  • 每一個VM供應商均可以支持更多的natvie代碼。
  • 工具構建器沒必要維護不一樣類型的natvie方法接口。
  • 應用程序編程人員將可以編寫其natvie代碼的一個版本,該版本將在不一樣的VM上運行。

實現標準本機方法接口的最佳方法是讓全部各方都參與Java VM。所以,咱們在Java許可證持有者之間組織了一系列關於統一本機方法接口設計的討論。從討論中能夠清楚地看出,標準本機方法接口必須知足如下要求:

  • 二進制兼容性 - 主要目標是在給定平臺上的全部Java VM實現中對本機方法庫進行二進制兼容。程序員應該只爲給定平臺維護其本機方法庫的一個版本。
  • 效率 - 爲了支持時間關鍵代碼,本機方法接口必須施加不多的開銷。確保VM獨立性(以及二進制兼容性)的全部已知技術都帶有必定量的開銷。咱們必須以某種方式在效率和VM獨立性之間達成妥協。
  • 功能 - 接口必須公開足夠的Java VM內部,以容許本機方法完成有用的任務。

4、實現JNI的方式討論

咱們但願採用現有方式之一做爲標準,主要是爲了給在不一樣VM中學習多個接口的程序員帶來最小的負擔。可是使人失望的是,目前沒有現有的解決方案來實現咱們這樣的想法。

Netscape的JRI是最接近咱們想要的的便攜式Natvie方法接口,並被用做咱們設計的起點。熟悉JRI的讀者會注意到API命名約定,方法和字段ID的使用,本地和全局引用的使用等方面的類似之處。儘管咱們盡最大努力,但JNI與JRI不是二進制兼容的,儘管VM能夠同時支持JRI和JNI。

微軟的RNI是對JDK 1.0的改進,由於它解決了使用非保守垃圾收集器的本機方法的問題。可是,RNI不適合做爲獨立於VM的本機方法接口。與JDK同樣,RNI本機方法將Java對象做爲C結構訪問,但也致使兩個問題:

  • RNI將內部Java對象的佈局暴露給本機代碼。
  • 直接訪問Java對象做爲C結構使得沒法有效地合併「寫入障礙」,這在高級垃圾收集算法中是必需的。 

做爲二進制標準,COM確保跨不一樣VM的徹底二進制兼容性。調用COM方法只須要間接調用,這幾乎不會產生任何開銷。此外,COM對象在解決版本問題方面比動態連接庫有了很大的改進。

可是,使用COM做爲標準Java本機方法接口受到如下幾個因素的阻礙:

  • 首先,Java / COM接口缺乏某些所需的功能,例如訪問私有字段和引起通常異常。
  • 其次,Java / COM接口自動爲Java對象提供標準的IUnknown和IDispatch COM接口,以便本機代碼能夠訪問公共方法和字段。遺憾的是,IDispatch接口不處理重載的Java方法,而且在匹配方法名稱時不區分大小寫。此外,經過IDispatch接口公開的全部Java方法都被包裝以執行動態類型檢查和強制。這是由於IDispatch接口在設計時考慮了弱類型語言(例如Basic)。
  • 第三,COM不是處理單獨的低級功能,而是旨在容許軟件組件(包括完整的應用程序)協同工做。咱們認爲將全部Java類或低級本機方法視爲軟件組件是不合適的。
  • 第四,因爲缺少對UNIX平臺的支持,所以當即採用COM受到阻礙。

雖然Java對象不做爲COM對象公開給本機代碼,但JNI接口自己與COM二進制兼容。JNI使用與COM相同的跳轉表結構和調用約定。這意味着,只要跨平臺支持COM,JNI就能夠成爲Java VM的COM接口。

JNI不被認爲是給定Java VM支持的惟一本機方法接口。標準接口使程序員受益,他們但願將本機代碼庫加載到不一樣的Java VM中。在某些狀況下,程序員可能必須使用較低級別的VM特定接口來實現最高效率。在其餘狀況下,程序員可能使用更高級別的界面來構建軟件組件。實際上,隨着Java環境和組件軟件技術的日趨成熟,本機方法將逐漸失去意義。

5、總結

首先本文是譯文,原文地址爲:https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/intro.html

同時也是本人整理的JNI教程的第一篇,可能部份內容語法有點不通順,可是看完了也能基本瞭解JNI是什麼,產生的背景,以及JNI被實現的方式。

下面附一下學習JNI時推薦的參考資料:

相關文章
相關標籤/搜索