1. 程式人生 > >Java本地介面(JNI)程式設計指南和規範(第一章)

Java本地介面(JNI)程式設計指南和規範(第一章)

第一部分,介紹和指南(Part One: Introduction and Tutorial)

第一章 介紹 "JNI"是"Java"平臺的一個強大的功能。使用"JNI"的應用程式能能混合用例如"C"和"C++"語言編寫的原生代碼(native code),和用Java程式語言編寫的程式碼。"JNI"允許程式設計人員,在不丟棄在傳統編碼上的投入,來利用Java平臺功能。因為"JNI"是"Java"平臺的一部分,程式設計人員立馬解決互操作的問題,同時解決和Java平臺的所有的實現一起工作的問題。

這本書是"JNI"的程式設計指導和參考說明。書包含三個部分: .第二章通過簡單的例子,介紹"JNI"。這個說明,是給不熟悉"JNI"的初始使用者的。 .第三章到第十章構建了程式設計者的指南,這給出了大量JNI功能的全面介紹。我們通過一系列短而詳細描述的例子來展示"JNI"不同的功能,和展示被證明在"JNI"程式設計中有用的技術。 .第十一章到第十三章為所有的JNI型別和函式,展示明確的規範。這些章也被組織為參考說明服務。

這本書嘗試吸引廣泛的使用者,他們對JNI不同需求的。這指南和程式設計引導是為初始程式設計者,但有經驗的開發者和JNI的實現者可以找到更有用的參考章節在這指南和程式設計引導中。大多數讀者將可能是開發者,他們用"JNI"來寫應用程式。這本書的"你"術語將暗指用"JNI"程式設計的開發者(program with the JNI)。相反是"JNI"實現者(JNI implementors)或使用"JNI"寫的應用程式的終端使用者。

這本書假設你有"Java,C和C++"程式語言的基本知識。如果沒有,你可以參考許多有用的優秀的書本:Ken Arnold and James Gosling(Addison-Wesley,1998)寫的"The Java Programming Language, Second Edittion", Brian Kernighan and Dennis Ritchie(Prentice Hall,1988)寫的"The C Programming Language, Second Edition"和Bjarne Stroustrup(Addison-Wesley 1997)寫的"The C++ Programming Language, Third Edition".

這章剩餘的部分介紹JNI的背景,作用和演化。

1.1 The Java Platform and Host Environment(Java平臺和主機環境) 這本書時間用Java程式語言和用本地程式語言(C,C++等(etc.))來寫應用程式.讓我們先為這些語言,明確正確的程式設計環境區域。

"Java"平臺的程式設計環境包含"Java"虛擬機器(VM)和Java應用程式程式設計的介面(Java Application Programming Interface(API))。"Java"應用程式是用"Java"程式語言編寫的,被編譯成一個獨立於機器(machine-independent)二進位制類格式.一個類在任何Java虛擬機器上執行實現。Java的API包含預定義的類集合。Java"平臺的任何實現被假設支援Java程式語言,虛擬機器和"API"。

主機環境(host environment)術語代表主機作業系統,本地庫組,和CPU指令集。用本地變成語言(native programming languages)如"C"和"C++"編寫本地應用程式(Native application),被編譯特定主機的二進位制編碼,和被連線到本地庫。本地應用程式和本地庫是典型依賴於特定主機環境。為一個作業系統建立的一個"C"應用程式,例如,典型不能呢工作在另一作業系統上。

"Java"平臺被一般的配置在主機環境的上面。例如,"JRE"(Java Runtime Enviroment)是"Sun"產品,它支援"Java"平臺執行在例如"Solaris"和"Windows"的存在作業系統上。"Java"平臺提供一組特性,應用程式能依賴獨立於底下的主機環境。

1.2 Role of the JNI(JNI的作用) 當"Java"平臺被配置在主機環境的頂層上,平臺對於允許"Java"應用程式,帶有用其他語言編寫地本機編碼工作,是需要或必須的。程式設計者已經開始採用Java平臺來建立用"C"和"C++"編寫的傳統的應用程式。因為在遺留程式碼上存在投資價值,然而,"Java"應用程式將和"C"和"C++"程式碼共存許多年。

JNI的一個強大的特性是允許你來利用"Java"平臺,但利用的程式碼仍然用其他語言來編寫。作為"Java"虛擬機器(Jave virtual machine)執行的一部分,"JNI"是一個雙向介面,允許Java應用程式呼叫原生代碼,反之亦然(vice versa)。Figure 1.1(圖1.1)說明"JNI"的作用。

Java application  <->  Java virtual machine (JNI) <-> Native application and library            implementation                 and library                               |                         |                               |-> Host enviroment  <----|

Figure 1.1 Role of JNI

"JNI"被設計為處理你需要聯合"Java"應用程式和原生代碼的情況。做為一個雙向介面,"JNI"能支援兩種本地編碼:本地庫(native libraries)和本地應用程式(native application)。 .你能使用"JNI"來編寫,允許Java應用程式來呼叫在本地庫中實現的函式的本地方法(native method)。"Java"應用程式,通過和他們呼叫在Java程式語言中實現的方法一樣辦法,呼叫本地方法。然而幕後,本地方法是用另一種語言實現的和位於本地庫中。 ."JNI"支援一個呼叫介面(invocation interface),這個介面允許你嵌入一個Java虛擬機器執行到你本地應用程式中。本地應用程式能和執行Java虛擬機器的本地庫連結,同樣因此用呼叫介面來執行用Java程式語言編寫的軟體控制元件。例如,一個用"C"寫的"web"瀏覽器能在嵌入式Java虛擬機器執行中執行下載"applets"。

1.3 Implications of Using the JNI(使用JNI的影響) 記住一旦一個應用程式使用了JNI,它冒險失去了Java平臺的兩個好處。

首先,依賴"JNI"的"Java"應用程式不再可以在多種主機環境中執行。即使用Java程式語言編寫的應程式的部分可移植到多種主機環境,它將需要重新編譯用本地程式語言編寫的應用程式的部分。

其次,Java程式語言的型別安全和可靠,然而本地語言例如"C"或"C++"是沒有的。因此,當你用JNI來寫應用程式時你必須額外地細心。一個有惡意的本地方法可能破壞整個應用程式。因為這個原因,Java應用程式在呼叫JNI特性前,接受了安全檢查。

作為一般規則,你應該構建應用程式時,在儘量少的類中定義本地方法。這就意味著在原生代碼和應用程式剩餘程式碼之間有一個明顯的隔離。

1.4 When to Use the JNI(什麼時間使用JNI) 在你從事一個使用"JNI"的工程前,後退一步調查一下是不是有根合理的替代方案是值得的。像上一章提到的,當和嚴格用"Java"程式語言寫的應用程式比時,使用"JNI"的應用程式有固有的缺點。例如,你失去Java程式語言的型別安全保證。

大量的可選方案也允許"Java"應用程式和其他語言編寫的程式碼互操作的。例如: ."Java"應用程式通過一個"TCP/IP"連結和其他程序間通訊機制(other inter-process communication(IPC) mechanisms)來和本地應用程式交流。 .一個"Java"應用程式可以通過"JDBC API"連線到原來的資料庫上。 .一個"Java"應用程式可以利用分散式物件技術例如"Java IDL API"

這些替代方案的一般特徵是"Java"應用程式和原生代碼放在不同的程序中(在一些案例中在不同的機器上).程序隔離提供了一個重要的好處。程序提供了地址空間的保護能夠最大限度的錯誤隔離,一個奔潰的本地應用程式不會立馬終止通過"TCP/IP"和它通訊的"Java"應用程式。

然而有時,你可以發現對於"Java"應用程式必須和駐留在一樣程序中(resides in the same process)的原生代碼交流。這是"JNI"很有用的時候。思考,例如,下面的情況: ."Java API"可能不支援應用需要的某個依賴主機的特性。例如:一個應用程式可能需要執行特別的檔案操作,但Java API不支援。然而通過另一個程序來操作檔案是繁瑣和低效的。 .你可能需要訪問一個存在的本地庫,不願意花費在不同程序間的資料的拷貝和複製的開銷。在同一個程序中載入本地庫是更有效率的。 .橫跨多個程序的應用程式可能導致不可接受的記憶體佔用。如果這些程序需要駐留在同一個客戶端機器上,這是真確的。載入一個本地庫到存在本機程序中,應用程式需要比啟動一個新的程序並載入這個庫到新程序中需要的更少的系統資源。 .你可能需要在一個低階語言中執行一小段時間要求嚴格的程式碼(實時反應的程式碼)(time-critical code),例如彙編。如果一個"3D"增強應用程式消耗大量的時間在圖形繪製中,你可以發現必須用匯編程式碼寫圖形庫的核心部分來達到最好效能。

總之,如果你的Java應用程式必須和駐留在一個程序中的原生代碼互操作,就得用"JNI".

1.5 Evolution of the JNI(JNI的演化) 從"Java"平臺的很早的時候,對於"Java"應用程式對和原生代碼互操作的需要的就被認識。"Java"平臺的第一版本,"JDK(Java Development Kit) release 1.0", 就包含一個本地方法介面。它允許Java應用程式呼叫其他語言如"C"和"C++"編寫的函式。許多第三方的應用程式和Java類庫的實現(例如,包擴java.lang,java.io and java.net),都依賴本地方法介面來訪問在底層主機環境中的特性。

不幸的是,在"JDK release 1.0"中的本地方法介面發現兩個主要的問題: .首先,原生代碼,用C結構體的成員作為物件,來訪問域。然而,Java虛擬機器規範沒有定義物件在記憶體中怎樣佈置。如果一個Java虛擬機器的實現以一種方法佈局這些物件,不同於本地方法介面的設定方法,你必須重編譯本地方法庫。 .其次,在"JDK release 1.0"中本地方法的介面依賴於一個保守的垃圾收集器,因為本地方法在虛擬機器中得到物件的直接指標。任何使用更先進的垃圾收集演算法的虛擬機器的實現,不可能支援在"JDK release 1.0"中的本地方法介面。

設計"JNI"來克服這些問題。一個介面能被在不同主機環境中的所有的Java虛擬機器的實現支援。有"JNI": .每個虛擬機器的實現者能支援很大體積的原生代碼。 .開發工具商不必處理不同種類的本地介面。 .最重要的,應用程式程式設計者可以寫一個版本的原生代碼,這個版本將能在不同的Java虛擬機器實現上執行。

"JNI"首先在"JDK release 1.1"中被支援。然而, "JDK release 1.1"內在仍然使用老風格的本地方法(和在"JDK release 1.0"中一樣)來執行"Java APIs".在"Java 2 SDK release 1.2"中不再是這樣(以前被稱為"JDK release 1.2").本地方法被重寫, 為了確定"JNI"標準。

"JNI"是被所有Java虛擬機器實現支援的本機介面。從"JDK release 1.1"開始,你應該用"JNI"程式設計。老風格本地方法介面仍然在"Java 2 SDK release 1.2"中被支援,但將在未來高階的Java虛擬機器實現中不被支援。

"Java 2 SDK relase 1.2"包含了大量的JNI增強效能。這個增強是向後相容的。"JNI"的將來的演化將相容保留所有的二進位制。

1.6 Example Programs(例子程式) 這本書包含大量例子程式,它們來證明"JNI"特性。典型的例子吃呢供需包含多段用"Java"程式語言和"C"或"C++"本地程式語言編寫的程式碼片段。有時本地編碼參考了在Solaris和Win32系統中的本機特定特性。我們也顯示了怎樣使用JDK和Java 2SDK release帶有的命令列工具(例如"javah")來建立"JNI"程式。

記住"JNI"的使用被限制在指定的主機環境或指定的應用開發工具中。這本書關心的是寫程式碼,不是在使用工具編譯和執行編碼上。和"JDK"和"Java 2 SDK release"捆綁的命令列工具是很原始的。第三方的工具可以提供改善的方法編譯使用JNI的應用程式。我們鼓勵你參考和你選擇的開發工具繫結的"JNI"相關的文件。