目錄
第一章 介紹
第二章 設(shè)計機制
第三章 JNI類型和數(shù)據(jù)結(jié)構(gòu)
第四章 JNI函數(shù)(1)
第四章 JNI函數(shù)(2)
第四章 JNI函數(shù)(3)
第四章 JNI函數(shù)(4)
第五章 Invocation API
前言
因為目前市面上關(guān)于JNI的中文資料都比較分散弛矛,且不太全面和深入地回,因此在學(xué)習(xí)JNI的過程中,主要針對目前最新版的JNI 6.0官方技術(shù)文檔進行理解性的翻譯嘲叔,并根據(jù)JVM源碼和網(wǎng)上各方面資料穿插一些個人的理解內(nèi)容,整理并形成這份中文版JNI技術(shù)指南驹吮。若有翻譯或理解不當(dāng)之處速妖,望指出。
英文版官方文檔《Java Native Interface 6.0 Specification》請查閱:
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html
除了此文檔之外椎眯,更多關(guān)于JNI的知識,可以查閱Sheng Liang在1999年出版的:
《The Java Native Interface: Programmer's Guide and Specification》一書胳岂。
本文檔的大多數(shù)內(nèi)容該書都涉及到了编整,并還有一些補充知識和例子。Sheng Liang博士曾是SUN公司JVM團隊的主要開發(fā)者之一乳丰,耶魯大學(xué)計算機博士掌测。
另外需要注意的是本文中的大部分內(nèi)容基于官方文檔的翻譯內(nèi)容,但中間穿插了一些個人理解性的內(nèi)容产园,這些內(nèi)容并非官方文檔的一部分赏半,僅是個人對于文檔的理解,因為可能會存在理解不當(dāng)?shù)牡胤较剑赃@部分在文中都會進行特別標注或說明断箫,避免對讀者造成任何誤導(dǎo)。
?
之所以對此文檔進行如此細致的研讀工作秋冰,主要是因為JNI的相關(guān)文檔并不多仲义,特別是中文資料,而這份英文的官方技術(shù)規(guī)范是目前市面上最權(quán)威也是最全面的文檔剑勾,研讀此文檔有助于對于JNI知識有一個比較全面而深入的了解埃撵。而且因為這份文檔包含了所有的JNI函數(shù)方法,因此也有參考手冊的作用虽另,今后在使用JNI技術(shù)的過程中也可查閱本文檔以作參考暂刘。
?
?
第一章 介紹
1.1 JNI簡介
JNI全稱為Java Native Interface. 它可以簡單理解為是本地方法的接口,即允許在Java虛擬機里面的Java代碼可以和如C捂刺,C++等其他底層語言進行交互(即可互相調(diào)用)谣拣。
一般情況下募寨,當(dāng)你無法用純Java來實現(xiàn)需求的時候,就需要使用JNI來用底層語言編寫的本地方法來滿足這些該需求森缠。
例如以下的幾種場景可能需要用到JNI:
- Java庫無法提供基于平臺系統(tǒng)相關(guān)特性的功能拔鹰,如平臺特有的功能或接口等。
- 已經(jīng)用其他語言寫好的庫贵涵,需要用Java調(diào)用列肢,而不想重現(xiàn)編碼,而想直接復(fù)用它們宾茂。
- 希望實現(xiàn)一部分時間和性能要求都很高的邏輯瓷马,需要用底層語言來編寫,如視頻圖片處理跨晴,游戲邏輯等欧聘。
?
使用JNI,你可以使用本地方法來:
- 創(chuàng)造坟奥,交互,更新Java對象(包括array和string)
- 調(diào)用Java方法拇厢。
- catch或拋出異常爱谁。
- 載入Java Class,獲取class信息孝偎。
- 執(zhí)行運行時類型檢查(runtime type checking)
當(dāng)你使用JNI的 Invocation API 可以允許任何本地應(yīng)用內(nèi)嵌Java虛擬機访敌,這允許程序員非常簡單的可以使已經(jīng)寫好的程序變成 Java-enabled , 而不需要鏈接到虛擬機源碼。
當(dāng)然你還可以使用JNI來使得Java方法可以直接調(diào)用本地方法衣盾。本地方法也可以調(diào)用Java方法寺旺。
?
1.2 歷史背景
歷史上存在過不同本地方法接口的實現(xiàn),各自不同势决,這使得開發(fā)者不得不編寫阻塑,維護和發(fā)布多種不同的版本。
簡單的回顧一下一些存在過的本地方法接口:
- JDK 1.0內(nèi)置的 native method interface
- 網(wǎng)景的 Java Runtime Interface
- 微軟的 Raw Native Interface and JAVA/COM interface
?
JDK 1.0內(nèi)置的Native Method Interface
在JDK 1.0的時候舊內(nèi)置了一套native method interface的機制果复,但不幸的是陈莽,因為兩個主要的原因使得其他Java虛擬機不適合接受它們。
- 首先虽抄,本地方法像訪問C里面的結(jié)構(gòu)體(structures)的成員一樣去訪問Java對象里的字段走搁,但是Java語言規(guī)范里面又沒有定義對象如何在內(nèi)存中放置。如果Java虛擬機以不同的方式來放置這些對象迈窟,則開發(fā)者則必須重新編譯本地代碼庫來適應(yīng)它們私植。
- 第二的問題,JDK 1.0的native method interface依賴于一個保守的垃圾收集器(GC)车酣∏冢可以無限制的使用
unhand
指令索绪,例如made it necessary to conservatively scan the native stack.
?
網(wǎng)景的 Java Runtime Interface
網(wǎng)景曾經(jīng)提出 Java Runtime Interface(JRI), 一個由Java虛擬機提供的通用接口服務(wù)。JRI的設(shè)計考慮到了移植性--它對基礎(chǔ)Java虛擬機的實現(xiàn)做了很少的假設(shè)躯肌。JRI討論了大量的問題者春,包括本地方法,調(diào)試清女,反射钱烟,內(nèi)嵌等問題。
?
微軟的 Raw Native Interface and Java/COM Interface
微軟的Java虛擬機提供兩種native method interface嫡丙。
在底層拴袭,它提供一個高效的 Raw Native Interface(RNI)。RNI提供高級和JDK 1.0提供的native method interface, 但由一個重要的區(qū)別在于曙博,本地方法不必依賴于保守的垃圾回收拥刻,而是必須使用RUN提供的函數(shù)來和垃圾回收器進行明確的交互。
在上層父泳,微軟的Java/COM接口為Java虛擬機提供與語言無關(guān)的標準二進制接口般哼。Java代碼可以像使用Java對象一樣使用COM對象。一個Java類也可以作為COM類暴露給系統(tǒng)的其他部分惠窄。
?
1.3 JNI的目標
JNI的目標就是提供一套統(tǒng)一的蒸眠,考慮充分的標準接口來為大家提供好處:
- 所有Java虛擬機都支持大量的本地代碼。
- 工具開發(fā)者不需要維護多種不同的本地方法接口杆融。
- 應(yīng)用開發(fā)者可以只寫一個版本的本地代碼楞卡,并且可以在不同的Java虛擬機上正常運行。
?
標準的統(tǒng)一的本地方法接口應(yīng)該滿足一下幾點要求:
- 二進制的兼容性脾歇。主要目的是提供本地方法庫訪問在所有平臺上實現(xiàn)的Java虛擬機的二進制兼容性蒋腮。
- 高效性。為了支持性能要求高的代碼藕各,本地方法接口必須執(zhí)行很少的開銷池摧。所有已知的技術(shù)在確保Java虛擬機的獨立性(以及二進制的兼容性)一定會帶來一定的開銷。所有必須以某種方法再效率和虛擬機獨立性之間尋求平衡點激况。
- 功能性险绘。接口必須暴露足夠的Java虛擬機內(nèi)部,來允許本地方法來訪問它們以完成有用的任務(wù)誉碴。
?
1.4 Java Native Interface Approach
我們希望采用現(xiàn)有的方法之一作為標準的JNI接口宦棺,因為這將減小程序員的學(xué)習(xí)負擔(dān)。 不幸的是黔帕,現(xiàn)有的解決方案不是太令人滿意代咸。
網(wǎng)景的 JRI 是最接近于我們想要實現(xiàn)的JNI接口,并作為了我們設(shè)計新的JNI接口的起點成黄。熟悉JRI的讀者會接近新的JNI接口命名呐芥,使用方法或成員域的ID逻杖,布局和全局變量等概念和JRI十分相似。盡管我們盡了最大努力思瘟,JNI也沒有完全兼容JRI荸百。
TODO
?
1.5 使用JNI編程
本地方法的開發(fā)者可以使用JNI編程。使用個JNI編程可以使你免受未知的問題困擾滨攻。只要通過滿足JNI標準够话,你就有能力和機會來在Java虛擬機上運行一個本地庫。
如果你正在實現(xiàn)一個Java虛擬機光绕,也應(yīng)該去實現(xiàn)JNI標準女嘲,JNI已經(jīng)經(jīng)過時間充分的測試,并確保不會對于實現(xiàn)一個Java虛擬機造成任何過多的開銷和限制诞帐,包括對象申明欣尼,垃圾回收等。如果有任何問題造成額外的開銷停蕉,可以聯(lián)系Java標準團隊愕鼓。
1.6 歷史版本更改
在 Java SE 6.0里,廢棄的 JDK1_1InitArgs
和 JDK1_1AttachArgs
已經(jīng)被移除慧起,卻而代之的是 JavaVMInitArgs
和 JavaVMAttachArgs
菇晃。