JNI技術規范 - 第一章 介紹

目錄

第一章 介紹
第二章 設計機制
第三章 JNI類型和數據結構
第四章 JNI函數(1)
第四章 JNI函數(2)
第四章 JNI函數(3)
第四章 JNI函數(4)
第五章 Invocation API

前言

因為目前市面上關于JNI的中文資料都比較分散,且不太全面和深入,因此在學習JNI的過程中,主要針對目前最新版的JNI 6.0官方技術文檔進行理解性的翻譯,并根據JVM源碼和網上各方面資料穿插一些個人的理解內容,整理并形成這份中文版JNI技術指南。若有翻譯或理解不當之處,望指出。

英文版官方文檔《Java Native Interface 6.0 Specification》請查閱:

http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html

除了此文檔之外,更多關于JNI的知識,可以查閱Sheng Liang在1999年出版的:

《The Java Native Interface: Programmer's Guide and Specification》一書。

本文檔的大多數內容該書都涉及到了,并還有一些補充知識和例子。Sheng Liang博士曾是SUN公司JVM團隊的主要開發者之一,耶魯大學計算機博士。

另外需要注意的是本文中的大部分內容基于官方文檔的翻譯內容,但中間穿插了一些個人理解性的內容,這些內容并非官方文檔的一部分,僅是個人對于文檔的理解,因為可能會存在理解不當的地方,所以這部分在文中都會進行特別標注或說明,避免對讀者造成任何誤導。

?

之所以對此文檔進行如此細致的研讀工作,主要是因為JNI的相關文檔并不多,特別是中文資料,而這份英文的官方技術規范是目前市面上最權威也是最全面的文檔,研讀此文檔有助于對于JNI知識有一個比較全面而深入的了解。而且因為這份文檔包含了所有的JNI函數方法,因此也有參考手冊的作用,今后在使用JNI技術的過程中也可查閱本文檔以作參考。

?

?

第一章 介紹

1.1 JNI簡介

JNI全稱為Java Native Interface. 它可以簡單理解為是本地方法的接口,即允許在Java虛擬機里面的Java代碼可以和如C,C++等其他底層語言進行交互(即可互相調用)。

一般情況下,當你無法用純Java來實現需求的時候,就需要使用JNI來用底層語言編寫的本地方法來滿足這些該需求。

例如以下的幾種場景可能需要用到JNI:

  • Java庫無法提供基于平臺系統相關特性的功能,如平臺特有的功能或接口等。
  • 已經用其他語言寫好的庫,需要用Java調用,而不想重現編碼,而想直接復用它們。
  • 希望實現一部分時間和性能要求都很高的邏輯,需要用底層語言來編寫,如視頻圖片處理,游戲邏輯等。

?

使用JNI,你可以使用本地方法來:

  • 創造,交互,更新Java對象(包括array和string)
  • 調用Java方法。
  • catch或拋出異常。
  • 載入Java Class,獲取class信息。
  • 執行運行時類型檢查(runtime type checking)

當你使用JNI的 Invocation API 可以允許任何本地應用內嵌Java虛擬機,這允許程序員非常簡單的可以使已經寫好的程序變成 Java-enabled , 而不需要鏈接到虛擬機源碼。

當然你還可以使用JNI來使得Java方法可以直接調用本地方法。本地方法也可以調用Java方法。

?

1.2 歷史背景

歷史上存在過不同本地方法接口的實現,各自不同,這使得開發者不得不編寫,維護和發布多種不同的版本。

簡單的回顧一下一些存在過的本地方法接口:

  • JDK 1.0內置的 native method interface
  • 網景的 Java Runtime Interface
  • 微軟的 Raw Native Interface and JAVA/COM interface

?

JDK 1.0內置的Native Method Interface

在JDK 1.0的時候舊內置了一套native method interface的機制,但不幸的是,因為兩個主要的原因使得其他Java虛擬機不適合接受它們。

  1. 首先,本地方法像訪問C里面的結構體(structures)的成員一樣去訪問Java對象里的字段,但是Java語言規范里面又沒有定義對象如何在內存中放置。如果Java虛擬機以不同的方式來放置這些對象,則開發者則必須重新編譯本地代碼庫來適應它們。
  2. 第二的問題,JDK 1.0的native method interface依賴于一個保守的垃圾收集器(GC)??梢詿o限制的使用 unhand 指令,例如 made it necessary to conservatively scan the native stack.

?

網景的 Java Runtime Interface

網景曾經提出 Java Runtime Interface(JRI), 一個由Java虛擬機提供的通用接口服務。JRI的設計考慮到了移植性--它對基礎Java虛擬機的實現做了很少的假設。JRI討論了大量的問題,包括本地方法,調試,反射,內嵌等問題。

?

微軟的 Raw Native Interface and Java/COM Interface

微軟的Java虛擬機提供兩種native method interface。

在底層,它提供一個高效的 Raw Native Interface(RNI)。RNI提供高級和JDK 1.0提供的native method interface, 但由一個重要的區別在于,本地方法不必依賴于保守的垃圾回收,而是必須使用RUN提供的函數來和垃圾回收器進行明確的交互。

在上層,微軟的Java/COM接口為Java虛擬機提供與語言無關的標準二進制接口。Java代碼可以像使用Java對象一樣使用COM對象。一個Java類也可以作為COM類暴露給系統的其他部分。

?

1.3 JNI的目標

JNI的目標就是提供一套統一的,考慮充分的標準接口來為大家提供好處:

  • 所有Java虛擬機都支持大量的本地代碼。
  • 工具開發者不需要維護多種不同的本地方法接口。
  • 應用開發者可以只寫一個版本的本地代碼,并且可以在不同的Java虛擬機上正常運行。

?

標準的統一的本地方法接口應該滿足一下幾點要求:

  • 二進制的兼容性。主要目的是提供本地方法庫訪問在所有平臺上實現的Java虛擬機的二進制兼容性。
  • 高效性。為了支持性能要求高的代碼,本地方法接口必須執行很少的開銷。所有已知的技術在確保Java虛擬機的獨立性(以及二進制的兼容性)一定會帶來一定的開銷。所有必須以某種方法再效率和虛擬機獨立性之間尋求平衡點。
  • 功能性。接口必須暴露足夠的Java虛擬機內部,來允許本地方法來訪問它們以完成有用的任務。

?

1.4 Java Native Interface Approach

我們希望采用現有的方法之一作為標準的JNI接口,因為這將減小程序員的學習負擔。 不幸的是,現有的解決方案不是太令人滿意。

網景的 JRI 是最接近于我們想要實現的JNI接口,并作為了我們設計新的JNI接口的起點。熟悉JRI的讀者會接近新的JNI接口命名,使用方法或成員域的ID,布局和全局變量等概念和JRI十分相似。盡管我們盡了最大努力,JNI也沒有完全兼容JRI。

TODO

?

1.5 使用JNI編程

本地方法的開發者可以使用JNI編程。使用個JNI編程可以使你免受未知的問題困擾。只要通過滿足JNI標準,你就有能力和機會來在Java虛擬機上運行一個本地庫。

如果你正在實現一個Java虛擬機,也應該去實現JNI標準,JNI已經經過時間充分的測試,并確保不會對于實現一個Java虛擬機造成任何過多的開銷和限制,包括對象申明,垃圾回收等。如果有任何問題造成額外的開銷,可以聯系Java標準團隊。

1.6 歷史版本更改

在 Java SE 6.0里,廢棄的 JDK1_1InitArgsJDK1_1AttachArgs 已經被移除,卻而代之的是 JavaVMInitArgsJavaVMAttachArgs 。

第二章 設計機制

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容