1. 程式人生 > >Java本機介面規範內容 第1章:簡介

Java本機介面規範內容 第1章:簡介

本章介紹Java Native Interface (JNI)。 JNI是本機程式設計介面。 它允許在Java虛擬機器(VM)內執行的Java程式碼與使用其他程式語言(如C,C ++和組合語言)編寫的應用程式和庫進行互操作。

JNI最重要的好處是它對底層Java VM的實現沒有任何限制。 因此,Java VM供應商可以新增對JNI的支援,而不會影響VM的其他部分。 程式設計師可以編寫一個本機應用程式或庫的版本,並期望它可以與支援JNI的所有Java VM一起使用。

目錄

歷史背景

目標

變化

雖然您可以完全使用Java編寫應用程式,但有些情況下Java本身並不能滿足您的應用程式的需求。 當應用程式無法完全用Java編寫時,程式設計師使用JNI編寫Java本機方法

來處理這些情況。

以下示例說明何時需要使用Java本機方法:

  • 標準Java類庫不支援應用程式所需的與平臺相關的功能。
  • 您已經有一個用另一種語言編寫的庫,並希望通過JNI使其可以訪問Java程式碼。
  • 您希望在較低級別的語言(如組合語言)中實現一小部分時間關鍵程式碼。

通過JNI程式設計,您可以使用本機方法:

  • 建立,檢查和更新Java物件(包括陣列和字串)。
  • 呼叫Java方法。
  • 捕獲並丟擲異常。
  • 載入類並獲取類資訊。
  • 執行執行時型別檢查。

您還可以將JNI與Invocation API一起使用,以使任意本機應用程式能夠嵌入Java VM。 這使程式設計師可以輕鬆地使其現有應用程式支援Java,而無需與VM原始碼連結。

歷史背景

來自不同供應商的VM提供不同的本機方法介面。 這些不同的介面迫使程式設計師在給定平臺上生成,維護和分發多個版本的本機方法庫。

我們簡要介紹一些本機方法介面,例如:

  • JDK 1.0本機方法介面
  • Netscape的Java執行時介面
  • Microsoft的原始本機介面和Java / COM介面

JDK 1.0附帶了本機方法介面。 不幸的是,這個介面不適合其他Java VM採用有兩個主要原因。

首先,本機程式碼訪問Java物件中的欄位作為C結構的成員。 但是, Java語言規範沒有定義物件在記憶體中的佈局方式。 如果Java VM在記憶體中以不同方式佈局物件,則程式設計師必須重新編譯本機方法庫。

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

Netscape提出了Java執行時介面(JRI),它是Java虛擬機器中提供的服務的通用介面。 JRI的設計考慮了可移植性 - 它對底層Java VM中的實現細節做了很少的假設。 JRI解決了廣泛的問題,包括本機方法,除錯,反射,嵌入(呼叫)等。

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

在更高級別,Microsoft的Java / COM介面為Java VM提供了與語言無關的標準二進位制介面。 Java程式碼可以像使用Java物件一樣使用COM物件。 Java類也可以作為COM類公開給系統的其餘部分。

目標

我們相信,統一,經過深思熟慮的標準介面為每個人提供以下好處:

  • 每個VM供應商都可以支援更大的本機程式碼。
  • 工具構建器不必維護不同型別的本機方法介面。
  • 應用程式程式設計人員將能夠編寫其本機程式碼的一個版本,該版本將在不同的VM上執行。

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

  • 二進位制相容性 - 主要目標是在給定平臺上的所有Java VM實現中對本機方法庫進行二進位制相容。 程式設計師應該只為給定平臺維護其本機方法庫的一個版本。
  • 效率 - 為了支援時間關鍵程式碼,本機方法介面必須施加很少的開銷。 確保VM獨立性(以及二進位制相容性)的所有已知技術都帶有一定量的開銷。 我們必須以某種方式在效率和VM獨立性之間達成妥協。
  • 功能 - 介面必須公開足夠的Java VM內部,以允許本機方法完成有用的任務。

我們希望採用現有方法之一作為標準介面,因為這會給必須在不同VM中學習多個介面的程式設計師帶來最小的負擔。 不幸的是,現有的解決方案在實現我們的目

Netscape的JRI最接近我們想象的行動式本機方法介面,並被用作我們設計的起點。 熟悉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環境和元件軟體技術的日趨成熟,本機方法將逐漸失去意義。

本機方法程式設計師應該程式設計到JNI。 對JNI進行程式設計可以使您免於未知,例如終端使用者可能正在執行的供應商的VM。 通過遵循JNI標準,您將為本機庫提供在給定Java VM中執行的最佳機會。

如果要實現Java VM,則應實現JNI。 JNI已經過時間測試,並確保不對您的VM實施施加任何開銷或限制,包括物件表示,垃圾收集方案等。 如果您遇到我們可能忽略的任何問題,請將您的反饋傳送給我們。

變化

從Java SE 6.0開始,已刪除不推薦使用的結構JDK1_1InitArgs和JDK1_1AttachArgs,而是使用JavaVMInitArgs和JavaVMAttachArgs。