版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
-/1-簡介本章介紹Java本地接口(JavaNativeInterface,JNI)。JNI是本地編程接口。它使得在Java虛擬機(jī)(VM)內(nèi)部運(yùn)行的Java代碼能夠與用其它編程語言(如C、C++和匯編語言)編寫的應(yīng)用程序和庫進(jìn)行互操作。謝謝閱讀JNI最重要的好處是它沒有對底層Java虛擬機(jī)的實現(xiàn)施加任何限制。因此,Java虛擬機(jī)廠商可以在不影響虛擬機(jī)其它部分的情況下添加對JNI的支持。程序員只需編寫一種版本的本地應(yīng)用程序或庫,就能夠與所有支持JNI的Java虛擬機(jī)協(xié)同工作。精品文檔放心下載本章論及以下主題:Java本地接口概述背景目標(biāo)Java本地接口方法利用JNI編程JDK1.1.2中的變化Java本地接口概述盡管可以完全用Java編寫應(yīng)用程序,但是有時單獨用Java不能滿足應(yīng)用程序的需要。程序員使用JNI來編寫Java本地方法,可以處理那些不能完全用Java編寫應(yīng)用程序的情況。精品文檔放心下載以下示例說明了何時需要使用Java本地方法:標(biāo)準(zhǔn)Java類庫不支持與平臺相關(guān)的應(yīng)用程序所需的功能。謝謝閱讀已經(jīng)擁有了一個用另一種語言編寫的庫,而又希望通過JNI使Java代碼能夠訪問該庫。精品文檔放心下載想用低級語言(如匯編語言)實現(xiàn)一小段時限代碼。通過用JNI編程,可以將本地方法用于:創(chuàng)建、檢查及更新Java對象(包括數(shù)組和字符串)。謝謝閱讀調(diào)用Java方法。捕捉和拋出異常。加載類和獲得類信息。-/執(zhí)行運(yùn)行時類型檢查。也可以與調(diào)用API一起使用JNI,以允許任意本地應(yīng)用程序嵌入到Java虛擬機(jī)中。這樣使得程序員能夠輕易地讓已有應(yīng)用程序支持Java,而不必與虛擬機(jī)源代碼相鏈接。精品文檔放心下載背景目前,不同廠商的虛擬機(jī)提供了不同的本地方法接口。這些不同的接口使程序員不得不在給定平臺上編寫、維護(hù)和分發(fā)多種版本的本地方法庫。謝謝閱讀下面簡要分析一下部分已有本地方法接口,例如:JDK1.0本地方法接口Netscape的Java運(yùn)行時接口Microsoft的原始本地接口和Java/COM接口精品文檔放心下載JDK1.0本地方法接口JDK1.0附帶有本地方法接口。遺憾的是,有兩點原因使得該接口不適合于其它Java虛擬機(jī)。感謝閱讀第一,平臺相關(guān)代碼將Java對象中的域作為C結(jié)構(gòu)的成員來進(jìn)行訪問。但是,Java語言規(guī)范沒有規(guī)定在內(nèi)存中對象是如何布局的。如果Java虛擬機(jī)在內(nèi)存中布局對象的方式有所不同,程序員就不得不重新編譯本地方法庫。精品文檔放心下載第二,JDK1.0的本地方法接口依賴于保守的垃圾收集器。例如,無限制地使用unhand宏使得有必要以保守方式掃描本地堆棧。感謝閱讀Java運(yùn)行時接口Netscape建議使用Java運(yùn)行時接口(JRI),它是Java虛擬機(jī)所提供服務(wù)的通用接口。JRI的設(shè)計融入了可移植性---它幾乎沒有對底層Java虛擬機(jī)的實現(xiàn)細(xì)節(jié)作任何假設(shè)。JRI提出了各種各樣的問題,包括本地方法、調(diào)試、反射、嵌入(調(diào)用)等等。精品文檔放心下載-/原始本地接口和Java/COM接口MicrosoftJava虛擬機(jī)支持兩種本地方法接口。在低一級,它提供了高效的原始本地接口(RNI)。RNI提供了與JDK本地方法接口有高度源代碼級的向后兼容性,盡管它們之間還有一個主要區(qū)別,即平臺相關(guān)代碼必須用RNI函數(shù)來與垃圾收集器進(jìn)行顯式的交互,而不是依賴于保守的垃圾收集。感謝閱讀在高一級,Microsoft的Java/COM接口為Java虛擬機(jī)提供了與語言無關(guān)的標(biāo)準(zhǔn)二進(jìn)制接口。Java代碼可以象使用Java對象一樣來使用COM對象。Java類也可以作為COM類顯示給系統(tǒng)的其余部分。精品文檔放心下載目標(biāo)我們認(rèn)為統(tǒng)一的,經(jīng)過細(xì)致考慮的標(biāo)準(zhǔn)接口能夠向每個用戶提供以下好處:謝謝閱讀每個虛擬機(jī)廠商都可以支持更多的平臺相關(guān)代碼。工具構(gòu)造器不必維護(hù)不同的本地方法接口。應(yīng)用程序設(shè)計人員可以只編寫一種版本的平臺相關(guān)代碼就能夠在不同的虛擬機(jī)上運(yùn)行。感謝閱讀獲得標(biāo)準(zhǔn)本地方法接口的最佳途徑是聯(lián)合所有對Java虛擬機(jī)有興趣的當(dāng)事方。因此,我們在Java獲得許可方之間組織了一系列研討會,對設(shè)計統(tǒng)一的本地方法接口進(jìn)行了討論。從研討會可以明確地看出標(biāo)準(zhǔn)本地方法接口必須滿足以下要求:精品文檔放心下載二進(jìn)制兼容性-主要的目標(biāo)是在給定平臺上的所有Java虛擬機(jī)實現(xiàn)之間實現(xiàn)本地方法庫的二進(jìn)制兼容性。對于給定平臺,程序員只需要維護(hù)一種版本的本地方法庫。感謝閱讀效率-若要支持時限代碼,本地方法接口必須增加一點系統(tǒng)開銷。所有已知的用于確保虛擬機(jī)無關(guān)性(因而具有二進(jìn)制兼容性)的技術(shù)都會占用一定的系統(tǒng)開銷。我們必須在效率與虛擬機(jī)無關(guān)性之間進(jìn)行某種折衷。感謝閱讀功能-接口必須顯示足夠的Java虛擬機(jī)內(nèi)部情況以使本地方法能夠完成有用的任務(wù)。感謝閱讀Java本地接口方法-/我們希望采用一種已有的方法作為標(biāo)準(zhǔn)接口,因為這樣程序員(程序員不得不學(xué)習(xí)在不同虛擬機(jī)中的多種接口)的工作負(fù)擔(dān)最輕。遺憾的是,已有解決方案中沒有任何方案能夠完全地滿足我們的目標(biāo)。謝謝閱讀Netscape的JRI最接近于我們所設(shè)想的可移植本地方法接口,因而我們采用它作為設(shè)計起點。熟悉JRI的讀者將會注意到在API命名規(guī)則、方法和域ID的使用、局部和全局引用的使用,等等中的相似點。雖然我們進(jìn)行了最大的努力,但是JNI并不具有對JRI的二進(jìn)制兼容性,不過虛擬機(jī)既可以支持JRI,又可以支持JNI。精品文檔放心下載Microsoft的RNI是對JDK1.0的改進(jìn),因為它可以解決使用非保守的垃圾收集器的本地方法的問題。然而,RNI不適合用作與虛擬機(jī)無關(guān)的本地方法接口。謝謝閱讀JDK類似,RNI本地方法將Java對象作為C結(jié)構(gòu)來訪問。這將導(dǎo)致兩個問題:謝謝閱讀RNI將內(nèi)部Java對象的布局暴露給了平臺相關(guān)代碼。精品文檔放心下載將Java對象作為C結(jié)構(gòu)直接進(jìn)行訪問使得不可能有效地加入“寫屏障”,寫屏障是高級的垃圾收集算法所必需的。感謝閱讀作為二進(jìn)制標(biāo)準(zhǔn),COM確保了不同虛擬機(jī)之間的完全二進(jìn)制兼容性。調(diào)用COM方法只要求間接調(diào)用,而這幾乎不會占用系統(tǒng)開銷。另外,COM對象對動態(tài)鏈接庫解決版本問題的方式也有很大的改進(jìn)。謝謝閱讀然而,有幾個因素阻礙了將COM用作標(biāo)準(zhǔn)Java本地方法接口:感謝閱讀第一,Java/COM接口缺少某些必需功能,例如訪問私有域和拋出普通異常。謝謝閱讀第二,Java/COM接口自動為Java對象提供標(biāo)準(zhǔn)的IUnknown和IDispatchCOM接口,因而平臺相關(guān)代碼能夠訪問公有方法和域。遺憾的是,IDispatch接口不能處理重載的Java方法,而且在匹配方法名稱時不區(qū)別大小寫。另外,通過IDispatch接口暴露的所有Java方法被打包在一起來執(zhí)行動態(tài)類型檢查和強(qiáng)制轉(zhuǎn)換。這是因為IDispatch接口的設(shè)計只考慮到了弱類型的語言(例如Basic)。精品文檔放心下載第三,COM允許軟件組件(包括完全成熟的應(yīng)用程序)一起工作,而不是處理單個低層函數(shù)。我們認(rèn)為將所有Java類或低層本地方法都當(dāng)作軟件組件是不恰當(dāng)?shù)摹Vx謝閱讀第四,在UNIX平臺上由于缺少對COM的支持,所以阻礙了直接采用感謝閱讀COM。雖然我們沒有將Java對象作為COM對象暴露給平臺相關(guān)代碼,但是JNI接口自身與COM具有二進(jìn)制兼容性。我們采用與COM一樣的跳轉(zhuǎn)表和調(diào)用約定。這謝謝閱讀意味著,一旦具有對COM的跨平臺支持,JNI就能成為Java虛擬機(jī)的COM接口。謝謝閱讀-/我們認(rèn)為JNI不應(yīng)該是給定Java虛擬機(jī)所支持的唯一的本地方法接口。標(biāo)準(zhǔn)接口的好處在于程序員可以將自己的平臺相關(guān)代碼庫加載到不同的Java虛擬機(jī)上。在某些情況下,程序員可能不得不使用低層且與虛擬機(jī)有關(guān)的接口來獲得較高的效率。但在其它情況下,程序員可能使用高層接口來建立軟件組件。實際上,我們希望隨著Java環(huán)境和組件軟件技術(shù)發(fā)展得越來越成熟,本地方法將變得越來越不重要。感謝閱讀利用JNI編程本地方法程序設(shè)計人員應(yīng)開始利用JNI進(jìn)行編程。利用JNI編程隔離了一些未知條件,例如終端用戶可能正在運(yùn)行的廠商的虛擬機(jī)。遵守JNI標(biāo)準(zhǔn)是本地庫能在給定Java虛擬機(jī)上運(yùn)行的最好保證。例如,雖然JDK1.1將繼續(xù)支持JDK1.0中所實現(xiàn)的舊式的本地方法接口,但是可以肯定的是JDK的未來版本將停止支持舊式的本地方法接口。依賴于舊式接口的本地方法將不得不重新編寫。謝謝閱讀如果您正在實現(xiàn)Java虛擬機(jī),則應(yīng)該實現(xiàn)JNI。我們(Javasoft和獲得許可方)盡力確保JNI不會占用虛擬機(jī)實現(xiàn)的系統(tǒng)開銷或施加任何限制,包括對象表示,垃圾收集機(jī)制等。如果您遇到了我們可能忽視了的問題,請告知我們。精品文檔放心下載JDK1.1.2中的變化為了更好地支持Java運(yùn)行時環(huán)境(JRE),在JDK1.1.2中對調(diào)用API在幾個方面作了擴(kuò)展。這些變化沒有破壞任何已有代碼,JNI本地方法接口也沒有改變。精品文檔放心下載JDK1_1InitArgs結(jié)構(gòu)中的reserved0域已被重新命名為version。JDK1_1InitArgs結(jié)構(gòu)保存JNI_CreateJavaVM的初始化參數(shù)。JNI_GetDefaultJavaVMInitArgs和JNI_CreateJavaVM的調(diào)用者必須將版本域設(shè)置為0x00010001。JNI_GetDefaultJavaVMInitArgs被更改為返回jint,用于表示是否支持所請求的版本。精品文檔放心下載JDK1_1InitArgs結(jié)構(gòu)中的reserved1域已被重新命名為properties。這是一個NULL-終結(jié)的字符串?dāng)?shù)組。每個字符串具有以下格式:謝謝閱讀name=value表示系統(tǒng)屬性(該功能對應(yīng)于Java命令行中的-D選項)。精品文檔放心下載在JDK1.1.1中,調(diào)用DestroyJavaVM的線程必須是虛擬機(jī)中的唯一用戶線程。JDK1.1.2放松了這一限制。如果調(diào)用DestroyJavaVM時有多感謝閱讀-/個用戶線程,則虛擬機(jī)將等待直到當(dāng)前線程成為唯一的用戶線程,然后銷毀自己。感謝閱讀-/2-設(shè)計概述本章著重討論JNI中的主要設(shè)計問題,其中的大部分問題都與本地方法有關(guān)。精品文檔放心下載調(diào)用API的設(shè)計將在第5章“調(diào)用API”中討論。感謝閱讀JNI接口函數(shù)和指針平臺相關(guān)代碼是通過調(diào)用JNI函數(shù)來訪問Java虛擬機(jī)功能的。JNI函數(shù)可通過接口指針來獲得。接口指針是指針的指針,它指向一個指針數(shù)組,而指針數(shù)組中的每個元素又指向一個接口函數(shù)。每個接口函數(shù)都處在數(shù)組的某個預(yù)定偏移量中。圖2-1說明了接口指針的組織結(jié)構(gòu)。精品文檔放心下載圖2-1接口指針JNI接口的組織類似于C++虛擬函數(shù)表或COM接口。使用接口表而不使用硬性編入的函數(shù)表的好處是使JNI名字空間與平臺相關(guān)代碼分開。虛擬機(jī)可以很容易地提供多個版本的JNI函數(shù)表。例如,虛擬機(jī)可支持以下兩個JNI函數(shù)表:謝謝閱讀一個表對非法參數(shù)進(jìn)行全面檢查,適用于調(diào)試程序;另一個表只進(jìn)行JNI規(guī)范所要求的最小程度的檢查,因此效率較高。精品文檔放心下載JNI接口指針只在當(dāng)前線程中有效。因此,本地方法不能將接口指針從一個線程傳遞到另一個線程中。實現(xiàn)JNI的虛擬機(jī)可將本地線程的數(shù)據(jù)分配和儲存在JNI接口指針?biāo)赶虻膮^(qū)域中。精品文檔放心下載本地方法將JNI接口指針當(dāng)作參數(shù)來接受。虛擬機(jī)在從相同的Java線程中對本地方法進(jìn)行多次調(diào)用時,保證傳遞給該本地方法的接口指針是相同的。但是,一個本地方法可被不同的Java線程所調(diào)用,因此可以接受不同的JNI接口指針。精品文檔放心下載-/加載和鏈接本地方法對本地方法的加載通過System.loadLibrary方法實現(xiàn)。下例中,類初始化方法加載了一個與平臺有關(guān)的本地庫,在該本地庫中給出了本地方法f的定義:謝謝閱讀packagepkg;classCls{nativedoublef(inti,Strings);謝謝閱讀static{System.loadLibrary("pkg_Cls");感謝閱讀}}System.loadLibrary的參數(shù)是程序員任意選取的庫名。系統(tǒng)按照標(biāo)準(zhǔn)的但與平感謝閱讀臺有關(guān)的處理方法將該庫名轉(zhuǎn)換為本地庫名。例如,Solaris系統(tǒng)將名稱感謝閱讀pkg_Cls轉(zhuǎn)換為libpkg_Cls.so,而Win32系統(tǒng)將相同的名稱pkg_Cls轉(zhuǎn)換為謝謝閱讀pkg_Cls.dll。程序員可用單個庫來存放任意數(shù)量的類所需的所有本地方法,只要這些類將被相同的類加載器所加載。虛擬機(jī)在其內(nèi)部為每個類加載器保護(hù)其所加載的本地庫清單。提供者應(yīng)該盡量選擇能夠避免名稱沖突的本地庫名。精品文檔放心下載如果底層操作系統(tǒng)不支持動態(tài)鏈接,則必須事先將所有的本地方法鏈接到虛擬機(jī)上。這種情況下,虛擬機(jī)實際上不需要加載庫即可完成System.loadLibrary調(diào)用。精品文檔放心下載程序員還可調(diào)用JNI函數(shù)RegisterNatives()來注冊與類關(guān)聯(lián)的本地方法。在與靜態(tài)鏈接的函數(shù)一起使用時,RegisterNatives()函數(shù)將特別有用。謝謝閱讀解析本地方法名動態(tài)鏈接程序是根據(jù)項的名稱來解析各項的。本地方法名由以下幾部分串接而成:感謝閱讀前綴Java_mangled全限定的類名下劃線(“_”)分隔符mangled方法名對于重載的本地方法,加上兩個下劃線(“__”),后跟mangled參數(shù)簽名謝謝閱讀-/虛擬機(jī)將為本地庫中的方法查找匹配的方法名。它首先查找短名(沒有參數(shù)簽名的名稱),然后再查找?guī)?shù)簽名的長名稱。只有當(dāng)某個本地方法被另一個本地方法重載時程序員才有必要使用長名。但如果本地方法的名稱與非本地方法的名稱相同,則不會有問題。因為非本地方法(Java方法)并不放在本地庫中。感謝閱讀下例中,不必用長名來鏈接本地方法g,因為另一個方法g不是本地方法,因而它并不在本地庫中。精品文檔放心下載classCls1{intg(inti);nativeintg(doubled);}我們采取簡單的名字?jǐn)噥y方案,以保證所有的Unicode字符都能被轉(zhuǎn)換為有效的C函數(shù)名。我們用下劃線(“_”)字符來代替全限定的類名中的斜杠謝謝閱讀(“/”)。由于名稱或類型描述符從來不會以數(shù)字打頭,我們用_0、...、_9來代替轉(zhuǎn)義字符序列,如表2-1所示:感謝閱讀2-1Unicode字符轉(zhuǎn)換轉(zhuǎn)義字符序列 表示_0XXXX Unicode字符XXXX。_1 字符“_”_2 簽名中的字符“;”_3 簽名中的字符“[”本地方法和接口API都要遵守給定平臺上的庫調(diào)用標(biāo)準(zhǔn)約定。例如,UNIX系統(tǒng)使用C調(diào)用約定,而Win32系統(tǒng)使用__stdcall。精品文檔放心下載本地方法的參數(shù)JNI接口指針是本地方法的第一個參數(shù)。其類型是JNIEnv。第二個參數(shù)隨本地方法是靜態(tài)還是非靜態(tài)而有所不同。非靜態(tài)本地方法的第二個參數(shù)是對對象的引用,而靜態(tài)本地方法的第二個參數(shù)是對其Java類的引用。精品文檔放心下載其余的參數(shù)對應(yīng)于通常Java方法的參數(shù)。本地方法調(diào)用利用返回值將結(jié)果傳回調(diào)用程序中。第3章“JNI的類型和數(shù)據(jù)結(jié)構(gòu)”將描述Java類型和C類型之間的映射。精品文檔放心下載代碼示例2-1說明了如何用C函數(shù)來實現(xiàn)本地方法f。對本地方法f的聲明如下:感謝閱讀-/packagepkg;classCls{nativedoublef(inti,Strings);感謝閱讀...}具有長mangled名稱Java_pkg_Cls_f_ILjava_lang_String_2的C函數(shù)實現(xiàn)本地方法f:謝謝閱讀代碼示例2-1:用C實現(xiàn)本地方法jdoubleJava_pkg_Cls_f__ILjava_lang_String_2(謝謝閱讀JNIEnv*env, /*接口指針*/jobjectobj, /*“this”指針*/感謝閱讀jinti, /*第一個參數(shù)*/jstrings) /*第二個參數(shù)*/{/*取得Java字符串的C版本*/constchar*str=(*env)->GetStringUTFChars(env,s,0);謝謝閱讀/*處理該字符串*/.../*至此完成對str的處理*/(*env)->ReleaseStringUTFChars(env,s,str);return...謝謝閱讀}注意,我們總是用接口指針env來操作Java對象??捎肅++將此代碼寫得稍微簡潔一些,如代碼示例2-2所示:感謝閱讀代碼示例2-2:用C++實現(xiàn)本地方法extern"C"/*指定C調(diào)用約定*/謝謝閱讀jdoubleJava_pkg_Cls_f__ILjava_lang_String_2(感謝閱讀JNIEnv*env, /*接口指針*/jobjectobj, /*“this”指針*/謝謝閱讀jinti, /*第一個參數(shù)*/jstrings) /*第二個參數(shù) */{constchar*str=env->GetStringUTFChars(s,0);謝謝閱讀...env->ReleaseStringUTFChars(s,str);精品文檔放心下載return...}-/使用C++后,源代碼變得更為直接,且接口指針參數(shù)消失。但是,C++的內(nèi)在機(jī)制與C的完全一樣。在C++中,JNI函數(shù)被定義為內(nèi)聯(lián)成員函數(shù),它們將擴(kuò)展為相應(yīng)的C對應(yīng)函數(shù)。精品文檔放心下載引用Java對象基本類型(如整型、字符型等)在Java和平臺相關(guān)代碼之間直接進(jìn)行復(fù)制。而Java對象由引用來傳遞。虛擬機(jī)必須跟蹤傳到平臺相關(guān)代碼中的對象,以使這些對象不會被垃圾收集器釋放。反之,平臺相關(guān)代碼必須能用某種方式通知虛擬機(jī)它不再需要那些對象,同時,垃圾收集器必須能夠移走被平臺相關(guān)代碼引用過的對象。謝謝閱讀全局和局部引用JNI將平臺相關(guān)代碼使用的對象引用分成兩類:局部引用和全局引用。局部引用在本地方法調(diào)用期間有效,并在本地方法返回后被自動釋放掉。全局引用將一直有效,直到被顯式釋放。感謝閱讀對象是被作為局部引用傳遞給本地方法的,由JNI函數(shù)返回的所有Java對象也都是局部引用。JNI允許程序員從局部引用創(chuàng)建全局引用。要求Java對象的JNI函數(shù)既可接受全局引用也可接受局部引用。本地方法將局部引用或全局引用作為結(jié)果返回。謝謝閱讀大多數(shù)情況下,程序員應(yīng)該依靠虛擬機(jī)在本地方法返回后釋放所有局部引用。但是,有時程序員必須顯式釋放某個局部引用。例如,考慮以下的情形:感謝閱讀本地方法要訪問一個大型Java對象,于是創(chuàng)建了對該Java對象的局部引用。然后,本地方法要在返回調(diào)用程序之前執(zhí)行其它計算。對這個大型Java對象的局部引用將防止該對象被當(dāng)作垃圾收集,即使在剩余的運(yùn)算中并不再需要該對象。謝謝閱讀本地方法創(chuàng)建了大量的局部引用,但這些局部引用并不是要同時使用。由于虛擬機(jī)需要一定的空間來跟蹤每個局部引用,創(chuàng)建太多的局部引用將可能使系統(tǒng)耗盡內(nèi)存。例如,本地方法要在一個大型對象數(shù)組中循環(huán),把取回的元素作為局部引用,并在每次迭代時對一個元素進(jìn)行操作。每次迭代后,程序員不再需要對該數(shù)組元素的局部引用。精品文檔放心下載JNI允許程序員在本地方法內(nèi)的任何地方對局部引用進(jìn)行手工刪除。為確保程序員可以手工釋放局部引用,JNI函數(shù)將不能創(chuàng)建額外的局部引用,除非是這些JNI函數(shù)要作為結(jié)果返回的引用。精品文檔放心下載-/局部引用僅在創(chuàng)建它們的線程中有效。本地方法不能將局部引用從一個線程傳遞到另一個線程中。感謝閱讀實現(xiàn)局部引用為了實現(xiàn)局部引用,Java虛擬機(jī)為每個從Java到本地方法的控制轉(zhuǎn)換都創(chuàng)建了注冊服務(wù)程序。注冊服務(wù)程序?qū)⒉豢梢苿拥木植恳糜成錇镴ava對象,并防止這些對象被當(dāng)作垃圾收集。所有傳給本地方法的Java對象(包括那些作為JNI函數(shù)調(diào)用結(jié)果返回的對象)將被自動添加到注冊服務(wù)程序中。本地方法返回后,注冊服務(wù)程序?qū)⒈粍h除,其中的所有項都可以被當(dāng)作垃圾來收集。精品文檔放心下載可用各種不同的方法來實現(xiàn)注冊服務(wù)程序,例如,使用表、鏈接列表或hash表來實現(xiàn)。雖然引用計數(shù)可用來避免注冊服務(wù)程序中有重復(fù)的項,但JNI實現(xiàn)不是必須檢測和消除重復(fù)的項。精品文檔放心下載注意,以保守方式掃描本地堆棧并不能如實地實現(xiàn)局部引用。平臺相關(guān)代碼可將局部引用儲存在全局或堆數(shù)據(jù)結(jié)構(gòu)中。精品文檔放心下載訪問Java對象JNI提供了一大批用來訪問全局引用和局部引用的函數(shù)。這意味著無論虛擬機(jī)在內(nèi)部如何表示Java對象,相同的本地方法實現(xiàn)都能工作。這就是為什么JNI可被各種各樣的虛擬機(jī)實現(xiàn)所支持的關(guān)鍵原因。感謝閱讀通過不透明的引用來使用訪問函數(shù)的開銷比直接訪問C數(shù)據(jù)結(jié)構(gòu)的開銷來得高。我們相信,大多數(shù)情況下,Java程序員使用本地方法是為了完成一些重要任務(wù),此時這種接口的開銷不是首要問題。感謝閱讀訪問基本類型數(shù)組對于含有大量基本數(shù)據(jù)類型(如整數(shù)數(shù)組和字符串)的Java對象來說,這種開銷將高得不可接受(考慮一下用于執(zhí)行矢量和矩陣運(yùn)算的本地方法的情形便知)。對Java數(shù)組進(jìn)行迭代并且要通過函數(shù)調(diào)用取回數(shù)組的每個元素,其效率是非常低的。精品文檔放心下載-/一個解決辦法是引入“釘住”概念,以使本地方法能夠要求虛擬機(jī)釘住數(shù)組內(nèi)容。而后,該本地方法將接受指向數(shù)值元素的直接指針。但是,這種方法包含以下兩個前提:感謝閱讀垃圾收集器必須支持釘住。虛擬機(jī)必須在內(nèi)存中連續(xù)存放基本類型數(shù)組。雖然大多數(shù)基本類型數(shù)組都是連續(xù)存放的,但布爾數(shù)組可以壓縮或不壓縮存儲。因此,依賴于布爾數(shù)組確切存儲方式的本地方法將是不可移植的。謝謝閱讀我們將采取折衷方法來克服上述兩個問題。首先,我們提供了一套函數(shù),用于在Java數(shù)組的一部分和本地內(nèi)存緩沖之間復(fù)制基本類型數(shù)組元素。這些函數(shù)只有在本地方法只需訪問大型數(shù)組中的一小部分元素時才使用。謝謝閱讀其次,程序員可用另一套函數(shù)來取回數(shù)組元素的受約束版本。記住,這些函數(shù)可能要求Java虛擬機(jī)分配存儲空間和進(jìn)行復(fù)制。虛擬機(jī)實現(xiàn)將決定這些函數(shù)是否真正復(fù)制該數(shù)組,如下所示:謝謝閱讀如果垃圾收集器支持釘住,且數(shù)組的布局符合本地方法的要求,則不需要進(jìn)行復(fù)制。精品文檔放心下載否則,該數(shù)組將被復(fù)制到不可移動的內(nèi)存塊中(例如,復(fù)制到C堆中),并進(jìn)行必要的格式轉(zhuǎn)換,然后返回指向該副本的指針。感謝閱讀最后,接口提供了一些函數(shù),用以通知虛擬機(jī)本地方法已不再需要訪問這些數(shù)組元素。當(dāng)調(diào)用這些函數(shù)時,系統(tǒng)或者釋放數(shù)組,或者在原始數(shù)組與其不可移動副本之間進(jìn)行協(xié)調(diào)并將副本釋放。謝謝閱讀這種處理方法具有靈活性。垃圾收集器的算法可對每個給定的數(shù)組分別作出復(fù)制或釘住的決定。例如,垃圾收集器可能復(fù)制小型對象而釘住大型對象。精品文檔放心下載JNI實現(xiàn)必須確保多個線程中運(yùn)行的本地方法可同時訪問同一數(shù)組。例如,JNI可以為每個被釘住的數(shù)組保留一個內(nèi)部計數(shù)器,以便某個線程不會解開同時被另一個線程釘住的數(shù)組。注意,JNI不必將基本類型數(shù)組鎖住以專供某個本地方法訪問。同時從不同的線程對Java數(shù)組進(jìn)行更新將導(dǎo)致不確定的結(jié)果。感謝閱讀訪問域和方法JNI允許本地方法訪問Java對象的域或調(diào)用其方法。JNI用符號名稱和類型簽名來識別方法和域。從名稱和簽名來定位域或?qū)ο蟮倪^程可分為兩步。例如,為調(diào)用類cls中的f方法,平臺相關(guān)代碼首先要獲得方法ID,如下所示:精品文檔放心下載-/jmethodIDmid=env->GetMethodID(cls,"f","(ILjava/lang/String;)D");感謝閱讀然后,平臺相關(guān)代碼可重復(fù)使用該方法ID而無須再查找該方法,如下所示:謝謝閱讀jdoubleresult=env->CallDoubleMethod(obj,mid,10,str);謝謝閱讀域ID或方法ID并不能防止虛擬機(jī)卸載生成該ID的類。該類被卸載之后,該方法ID或域ID亦變成無效。因此,如果平臺相關(guān)代碼要長時間使用某個方法ID或域ID,則它必須確保:感謝閱讀保留對所涉及類的活引用,或重新計算該方法ID或域ID。JNI對域ID和方法ID的內(nèi)部實現(xiàn)并不施加任何限制。感謝閱讀報告編程錯誤JNI不檢查諸如傳遞NULL指針或非法參數(shù)類型之類的編程錯誤。非法的參數(shù)類型包括諸如要用Java類對象時卻用了普通Java對象這樣的錯誤。JNI不檢查這些編程錯誤的理由如下:感謝閱讀強(qiáng)迫JNI函數(shù)去檢查所有可能的錯誤情況將降低正常(正確)的本地方法的性能。精品文檔放心下載在許多情況下,沒有足夠的運(yùn)行時的類型信息可供這種檢查使用。精品文檔放心下載大多數(shù)C庫函數(shù)對編程錯誤不進(jìn)行防范。例如,printf()函數(shù)在接到一個無效地址時通常是引起運(yùn)行錯而不是返回錯誤代碼。強(qiáng)迫C庫函數(shù)檢查所有可能的錯誤情況將有可能引起這種檢查被重復(fù)進(jìn)行--先是在用戶代碼中進(jìn)行,然后又在庫函數(shù)中再次進(jìn)行。精品文檔放心下載程序員不得將非法指針或錯誤類型的參數(shù)傳遞給JNI函數(shù)。否則,可能產(chǎn)生意想不到的后果,包括可能使系統(tǒng)狀態(tài)受損或使虛擬機(jī)崩潰。精品文檔放心下載Java異常JNI允許本地方法拋出任何Java異常。本地方法也可以處理突出的Java異常。未被處理的Java異常將被傳回虛擬機(jī)中。謝謝閱讀-/異常和錯誤代碼一些JNI函數(shù)使用Java異常機(jī)制來報告錯誤情況。大多數(shù)情況下,JNI函數(shù)通過返回錯誤代碼并拋出Java異常來報告錯誤情況。錯誤代碼通常是特殊的返回值(如NULL),這種特殊的返回值在正常返回值范圍之外。因此,程序員可以:感謝閱讀快速檢查上一個JNI調(diào)用所返回的值以確定是否出錯,并感謝閱讀通過調(diào)用函數(shù)ExceptionOccurred()來獲得異常對象,它含有對錯誤情況的更詳細(xì)說明。謝謝閱讀在以下兩種情況中,程序員需要先查出異常,然后才能檢查錯誤代碼:精品文檔放心下載調(diào)用Java方法的JNI函數(shù)返回該Java方法的結(jié)果。程序員必須調(diào)用ExceptionOccurred()以檢查在執(zhí)行Java方法期間可能發(fā)生的異常。精品文檔放心下載某些用于訪問JNI數(shù)組的函數(shù)并不返回錯誤代碼,但可能會拋出ArrayIndexOutOfBoundsException或ArrayStoreException。謝謝閱讀在所有其它情況下,返回值如果不是錯誤代碼值就可確保沒有拋出異常。謝謝閱讀異步異常在多個線程的情況下,當(dāng)前線程以外的其它線程可能會拋出異步異常。異步異常并不立即影響當(dāng)前線程中平臺相關(guān)代碼的執(zhí)行,直到出現(xiàn)下列情況:精品文檔放心下載該平臺相關(guān)代碼調(diào)用某個有可能拋出同步異常的JNI函數(shù),或者精品文檔放心下載該平臺相關(guān)代碼用ExceptionOccurred()顯式檢查同步異?;虍惒疆惓?。感謝閱讀注意,只有那些有可能拋出同步異常的JNI函數(shù)才檢查異步異常。謝謝閱讀本地方法應(yīng)在必要的地方(例如,在一個沒有其它異常檢查的緊密循環(huán)中)插入ExceptionOccurred()檢查以確保當(dāng)前線程可在適當(dāng)時間內(nèi)對異步異常作出響應(yīng)。感謝閱讀異常的處理-/可用兩種方法來處理平臺相關(guān)代碼中的異常:本地方法可選擇立即返回,使異常在啟動該本地方法調(diào)用的Java代碼中拋出。感謝閱讀平臺相關(guān)代碼可通過調(diào)用ExceptionClear()來清除異常,然后執(zhí)行自己的異常處理代碼。精品文檔放心下載拋出了某個異常之后,平臺相關(guān)代碼必須先清除異常,然后才能進(jìn)行其它的JNI調(diào)用。當(dāng)有待定異常時,只有以下這些JNI函數(shù)可被安全地調(diào)用:ExceptionOccurred()、ExceptionDescribe()和ExceptionClear()。ExceptionDescribe()函數(shù)將打印有關(guān)待定異常的調(diào)試消息。精品文檔放心下載-/3-JNI的類型和數(shù)據(jù)結(jié)構(gòu)本章討論JNI如何將Java類型映射到本地C類型。感謝閱讀基本類型表3-1描述Java基本類型及其與計算機(jī)相關(guān)的本地等效類型。謝謝閱讀表3-1基本類型和本地等效類型Java類型本地類型說明booleanjboolean無符號,8位bytejbyte無符號,8位charjchar無符號,16位shortjshort有符號,16位intjint有符號,32位longjlong有符號,64位floatjfloat32位doublejdouble64位voidvoidN/A為了使用方便,特提供以下定義。#defineJNI_FALSE0#defineJNI_TRUE1jsize整數(shù)類型用于描述主要指數(shù)和大?。簍ypedefjintjsize;引用類型-/JNI包含了很多對應(yīng)于不同Java對象的引用類型。JNI引用類型的組織層次如圖3-1所示。精品文檔放心下載圖3-1引用類型層次在C中,所有其它JNI引用類型都被定義為與jobject一樣。例如:謝謝閱讀typedefjobjectjclass;在C++中,JNI引入了虛構(gòu)類以加強(qiáng)子類關(guān)系。例如:謝謝閱讀class_jobject{};class_jclass:public_jobject{};精品文檔放心下載...typedef_jobject*jobject;精品文檔放心下載typedef_jclass*jclass;域ID和方法ID方法ID和域ID是常規(guī)的C指針類型:struct_jfieldID;/*不透明結(jié)構(gòu)*/typedefstruct_jfieldID*jfieldID;/*域ID*/感謝閱讀struct_jmethodID;/*不透明結(jié)構(gòu)*/typedefstruct_jmethodID*jmethodID;/*方法ID*/謝謝閱讀值類型-/jvalue聯(lián)合類型在參數(shù)數(shù)組中用作單元類型。其聲明方式如下:精品文檔放心下載typedefunionjvalue{jbooleanz;jbyte b;jchar c;jshort s;jint i;jlong j;jfloat f;jdouble d;jobject l;}jvalue;類型簽名JNI使用Java虛擬機(jī)的類型簽名表述。表3-2列出了這些類型簽名。精品文檔放心下載表3-2Java虛擬機(jī)類型簽名類型簽名 Java類型Z booleanB byteC charS shortI intJ longF floatD doubleLfully-qualified-class; 全限定的類謝謝閱讀[type type[](arg-types)ret-type 方法類型精品文檔放心下載例如,Java方法:longf(intn,Strings,int[]arr);精品文檔放心下載具有以下類型簽名:(ILjava/lang/String;[I)J-/UTF-8字符串JNI用UTF-8字符串來表示各種字符串類型。UTF-8字符串和Java虛擬機(jī)所使用的一樣。UTF-8字符串的編碼方式使得僅包含非空ASCII字符的字符序列能夠按每字符一個字節(jié)表示,但是最多只能表示16位的字符。所有在\u0001到\u007F范圍內(nèi)的字符都用單字節(jié)表示,如下所示:精品文檔放心下載字節(jié)中的七位數(shù)據(jù)確定了所表示字符的值??兆址?\u000)和\u0080到精品文檔放心下載\u07FF范圍內(nèi)的字符用一對字節(jié)表示,即x和y,如下所示:謝謝閱讀值為((x&0x1f)<<6)+(y&0x3f)的字符需用兩個字節(jié)表示。精品文檔放心下載\u0800到\uFFFF范圍內(nèi)的字符用三個字節(jié)表示,即x,y,和z:謝謝閱讀值為((x&0xf)<<12)+(y&0x3f)<<6)+(z&0x3f)的字符需用三個字節(jié)表示。謝謝閱讀此格式與“標(biāo)準(zhǔn)”UTF-8格式之間有兩個區(qū)別。第一,空字節(jié)(byte)0使用雙字節(jié)格式進(jìn)行編碼,而不是單字節(jié)格式。這意味著Java虛擬機(jī)的UTF-8字符串不可能有嵌入的空值。第二,只使用單字節(jié)、雙字節(jié)和三字節(jié)格式。Java虛擬機(jī)不能識別更長的UTF-8格式。精品文檔放心下載-/4-JNI函數(shù)本章為JNI函數(shù)提供參考信息。其中列出了全部JNI函數(shù),同時也給出了JNI函數(shù)表的準(zhǔn)確布局。謝謝閱讀注意:“必須”一詞用于約束JNI編程人員。例如,當(dāng)說明某個JNI函數(shù)必須接收非空對象時,就應(yīng)確保不要向該JNI函數(shù)傳遞NULL。這時,JNI實現(xiàn)將無需在該JNI函數(shù)中執(zhí)行NULL指針檢查。精品文檔放心下載本章的部分資料改編自Netscape的JRI文檔。感謝閱讀該參考資料按用法對函數(shù)進(jìn)行組織。參考部分按下列函數(shù)區(qū)域進(jìn)行組織:謝謝閱讀版本信息類操作異常全局及局部引用對象操作訪問對象的域調(diào)用實例方法訪問靜態(tài)域調(diào)用靜態(tài)方法字符串操作數(shù)組操作注冊本地方法監(jiān)視程序操作Java虛擬機(jī)接口接口函數(shù)表每個函數(shù)均可通過JNIEnv參數(shù)以固定偏移量進(jìn)行訪問。JNIEnv的類型是一個指針,指向存儲全部JNI函數(shù)指針的結(jié)構(gòu)。其定義如下:謝謝閱讀注意:前三項留作將來與COM兼容。此外,我們在函數(shù)表開頭部分也留出來多感謝閱讀NULL項,從而可將將來與類有關(guān)的JNI操作添加到FindClass后面,而非函數(shù)表的末尾。感謝閱讀注意,函數(shù)表可在所有JNI接口指針間共享。代碼示例4-1-/conststructJNINativeInterface...={精品文檔放心下載NULL,NULL,NULL,NULL,GetVersion,DefineClass,FindClass,NULL,NULL,NULL,GetSuperclass,IsAssignableFrom,NULL,Throw,ThrowNew,ExceptionOccurred,ExceptionDescribe,ExceptionClear,FatalError,NULL,NULL,NewGlobalRef,DeleteGlobalRef,DeleteLocalRef,IsSameObject,NULL,NULL,AllocObject,NewObject,NewObjectV,NewObjectA,-/GetObjectClass,IsInstanceOf,GetMethodID,CallObjectMethod,CallObjectMethodV,CallObjectMethodA,CallBooleanMethod,CallBooleanMethodV,CallBooleanMethodA,CallByteMethod,CallByteMethodV,CallByteMethodA,CallCharMethod,CallCharMethodV,CallCharMethodA,CallShortMethod,CallShortMethodV,CallShortMethodA,CallIntMethod,CallIntMethodV,CallIntMethodA,CallLongMethod,CallLongMethodV,CallLongMethodA,CallFloatMethod,CallFloatMethodV,CallFloatMethodA,CallDoubleMethod,CallDoubleMethodV,CallDoubleMethodA,CallVoidMethod,CallVoidMethodV,CallVoidMethodA,CallNonvirtualObjectMethod,謝謝閱讀-/CallNonvirtualObjectMethodV,謝謝閱讀CallNonvirtualObjectMethodA,精品文檔放心下載CallNonvirtualBooleanMethod,謝謝閱讀CallNonvirtualBooleanMethodV,精品文檔放心下載CallNonvirtualBooleanMethodA,感謝閱讀CallNonvirtualByteMethod,CallNonvirtualByteMethodV,精品文檔放心下載CallNonvirtualByteMethodA,感謝閱讀CallNonvirtualCharMethod,CallNonvirtualCharMethodV,精品文檔放心下載CallNonvirtualCharMethodA,感謝閱讀CallNonvirtualShortMethod,精品文檔放心下載CallNonvirtualShortMethodV,感謝閱讀CallNonvirtualShortMethodA,精品文檔放心下載CallNonvirtualIntMethod,CallNonvirtualIntMethodV,CallNonvirtualIntMethodA,CallNonvirtualLongMethod,CallNonvirtualLongMethodV,精品文檔放心下載CallNonvirtualLongMethodA,感謝閱讀CallNonvirtualFloatMethod,謝謝閱讀CallNonvirtualFloatMethodV,謝謝閱讀CallNonvirtualFloatMethodA,精品文檔放心下載CallNonvirtualDoubleMethod,精品文檔放心下載CallNonvirtualDoubleMethodV,精品文檔放心下載CallNonvirtualDoubleMethodA,謝謝閱讀CallNonvirtualVoidMethod,CallNonvirtualVoidMethodV,謝謝閱讀CallNonvirtualVoidMethodA,謝謝閱讀GetFieldID,GetObjectField,GetBooleanField,GetByteField,GetCharField,GetShortField,-/GetIntField,GetLongField,GetFloatField,GetDoubleField,SetObjectField,SetBooleanField,SetByteField,SetCharField,SetShortField,SetIntField,SetLongField,SetFloatField,SetDoubleField,GetStaticMethodID,CallStaticObjectMethod,CallStaticObjectMethodV,CallStaticObjectMethodA,CallStaticBooleanMethod,CallStaticBooleanMethodV,CallStaticBooleanMethodA,CallStaticByteMethod,CallStaticByteMethodV,CallStaticByteMethodA,CallStaticCharMethod,CallStaticCharMethodV,CallStaticCharMethodA,CallStaticShortMethod,CallStaticShortMethodV,CallStaticShortMethodA,CallStaticIntMethod,CallStaticIntMethodV,CallStaticIntMethodA,CallStaticLongMethod,CallStaticLongMethodV,CallStaticLongMethodA,-/CallStaticFloatMethod,CallStaticFloatMethodV,CallStaticFloatMethodA,CallStaticDoubleMethod,CallStaticDoubleMethodV,CallStaticDoubleMethodA,CallStaticVoidMethod,CallStaticVoidMethodV,CallStaticVoidMethodA,GetStaticFieldID,GetStaticObjectField,GetStaticBooleanField,GetStaticByteField,GetStaticCharField,GetStaticShortField,GetStaticIntField,GetStaticLongField,GetStaticFloatField,GetStaticDoubleField,SetStaticObjectField,SetStaticBooleanField,SetStaticByteField,SetStaticCharField,SetStaticShortField,SetStaticIntField,SetStaticLongField,SetStaticFloatField,SetStaticDoubleField,NewString,GetStringLength,GetStringChars,ReleaseStringChars,-/NewStringUTF,GetStringUTFLength,GetStringUTFChars,ReleaseStringUTFChars,GetArrayLength,NewObjectArray,GetObjectArrayElement,SetObjectArrayElement,NewBooleanArray,NewByteArray,NewCharArray,NewShortArray,NewIntArray,NewLongArray,NewFloatArray,NewDoubleArray,GetBooleanArrayElements,GetByteArrayElements,GetCharArrayElements,GetShortArrayElements,GetIntArrayElements,GetLongArrayElements,GetFloatArrayElements,GetDoubleArrayElements,ReleaseBooleanArrayElements,謝謝閱讀ReleaseByteArrayElements,ReleaseCharArrayElements,ReleaseShortArrayElements,精品文檔放心下載ReleaseIntArrayElements,ReleaseLongArrayElements,ReleaseFloatArrayElements,謝謝閱讀ReleaseDoubleArrayElements,感謝閱讀-/GetBooleanArrayRegion,GetByteArrayRegion,GetCharArrayRegion,GetShortArrayRegion,GetIntArrayRegion,GetLongArrayRegion,GetFloatArrayRegion,GetDoubleArrayRegion,SetBooleanArrayRegion,SetByteArrayRegion,SetCharArrayRegion,SetShortArrayRegion,SetIntArrayRegion,SetLongArrayRegion,SetFloatArrayRegion,SetDoubleArrayRegion,RegisterNatives,UnregisterNatives,MonitorEnter,MonitorExit,GetJavaVM,};版本信息GetVersionjintGetVersion(JNIEnv*env);精品文檔放心下載返回本地方法接口的版本。-/參數(shù)env:JNI接口指針。返回值:高16位返回主版本號,低16位返回次版本號。感謝閱讀在JDK1.1中,GetVersion()返回0x00010001。精品文檔放心下載類操作DefineClassjclassDefineClass(JNIEnv*env,jobjectloader,constjbyte*buf,jsizebufLen);精品文檔放心下載從原始類數(shù)據(jù)的緩沖區(qū)中加載類。參數(shù):env:JNI接口指針。loader:分派給所定義的類的類加載器。buf:包含.class文件數(shù)據(jù)的緩沖區(qū)。bufLen:緩沖區(qū)長度。返回值:返回Java類對象。如果出錯則返回NULL。拋出:ClassFormatError:如果類數(shù)據(jù)指定的類無效。謝謝閱讀ClassCircularityError:如果類或接口是自身的超類或超接口。謝謝閱讀OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。精品文檔放心下載-/FindClassjclassFindClass(JNIEnv*env,constchar*name);感謝閱讀該函數(shù)用于加載本地定義的類。它將搜索由CLASSPATH環(huán)境變量為具有指定名稱的類所指定的目錄和zip文件。感謝閱讀參數(shù):env:JNI接口指針。name:類全名(即包名后跟類名,之間由“/”分隔)。如果該名稱以“[”(數(shù)組簽名字符)打頭,則返回一個數(shù)組類。感謝閱讀返回值:返回類對象全名。如果找不到該類,則返回NULL。拋出:ClassFormatError:如果類數(shù)據(jù)指定的類無效。感謝閱讀ClassCircularityError:如果類或接口是自身的超類或超接口。精品文檔放心下載NoClassDefFoundError:如果找不到所請求的類或接口的定義。精品文檔放心下載OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。精品文檔放心下載GetSuperclassjclassGetSuperclass(JNIEnv*env,jclassclazz);謝謝閱讀如果clazz代表類而非類object,則該函數(shù)返回由clazz所指定的類的超類。感謝閱讀如果clazz指定類object或代表某個接口,則該函數(shù)返回NULL。謝謝閱讀參數(shù):env:JNI接口指針。-/clazz:Java類對象。返回值:由clazz所代表的類的超類或NULL。IsAssignableFromjbooleanIsAssignableFrom(JNIEnv*env,jclassclazz1,jclassclazz2);謝謝閱讀確定clazz1的對象是否可安全地強(qiáng)制轉(zhuǎn)換為clazz2。精品文檔放心下載參數(shù):env:JNI接口指針。clazz1:第一個類參數(shù)。clazz2:第二個類參數(shù)。返回值:下列某個情況為真時返回JNI_TRUE:第一及第二個類參數(shù)引用同一個Java類。第一個類是第二個類的子類。第二個類是第一個類的某個接口。異常ThrowjintThrow(JNIEnv*env,jthrowableobj);謝謝閱讀拋出java.lang.Throwable對象。精品文檔放心下載-/參數(shù):env:JNI接口指針。obj:java.lang.Throwable對象。精品文檔放心下載返回值:成功時返回0,失敗時返回負(fù)數(shù)。拋出:java.lang.Throwable對象obj。感謝閱讀ThrowNewjintThrowNew(JNIEnv*env,jclassclazz,謝謝閱讀constchar*message);利用指定類的消息(由message指定)構(gòu)造異常對象并拋出該異常。感謝閱讀參數(shù):env:JNI接口指針。clazz:java.lang.Throwable的子類。感謝閱讀message:用于構(gòu)造java.lang.Throwable對象的消息。感謝閱讀返回值:成功時返回0,失敗時返回負(fù)數(shù)。拋出:新構(gòu)造的java.lang.Throwable對象。感謝閱讀ExceptionOccurredjthrowableExceptionOccurred(JNIEnv*env);精品文檔放心下載-/確定是否某個異常正被拋出。在平臺相關(guān)代碼調(diào)用ExceptionClear()或Java代碼處理該異常前,異常將始終保持拋出狀態(tài)。感謝閱讀參數(shù):env:JNI接口指針。返回值:返回正被拋出的異常對象,如果當(dāng)前無異常被拋出,則返回NULL。謝謝閱讀ExceptionDescribevoidExceptionDescribe(JNIEnv*env);精品文檔放心下載將異常及堆棧的回溯輸出到系統(tǒng)錯誤報告信道(例如stderr)。該例程可便利調(diào)試操作。謝謝閱讀參數(shù):env:JNI接口指針。ExceptionClearvoidExceptionClear(JNIEnv*env);精品文檔放心下載清除當(dāng)前拋出的任何異常。如果當(dāng)前無異常,則此例程不產(chǎn)生任何效果。謝謝閱讀參數(shù):env:JNI接口指針。FatalErrorvoidFatalError(JNIEnv*env,constchar*msg);謝謝閱讀拋出致命錯誤并且不希望虛擬機(jī)進(jìn)行修復(fù)。該函數(shù)無返回值。精品文檔放心下載-/參數(shù):env:JNI接口指針。msg:錯誤消息。全局及局部引用NewGlobalRefjobjectNewGlobalRef(JNIEnv*env,jobjectobj);謝謝閱讀創(chuàng)建obj參數(shù)所引用對象的新全局引用。obj參數(shù)既可以是全局引用,也可以是局部引用。全局引用通過調(diào)用DeleteGlobalRef()來顯式撤消。謝謝閱讀參數(shù):env:JNI接口指針。obj:全局或局部引用。返回值:返回全局引用。如果系統(tǒng)內(nèi)存不足則返回NULL。DeleteGlobalRefvoidDeleteGlobalRef(JNIEnv*env,jobjectglobalRef);謝謝閱讀刪除globalRef所指向的全局引用。參數(shù):env:JNI接口指針。globalRef:全局引用。-/DeleteLocalRefvoidDeleteLocalRef(JNIEnv*env,jobjectlocalRef);刪除localRef所指向的局部引用。精品文檔放心下載參數(shù):env:JNI接口指針。localRef:局部引用。對象操作AllocObjectjobjectAllocObject(JNIEnv*env,jclassclazz);謝謝閱讀分配新Java對象而不調(diào)用該對象的任何構(gòu)造函數(shù)。返回該對象的引用。精品文檔放心下載clazz參數(shù)務(wù)必不要引用數(shù)組類。參數(shù):env:JNI接口指針。clazz:Java類對象。返回值:返回Java對象。如果無法構(gòu)造該對象,則返回NULL。精品文檔放心下載拋出:InstantiationException:如果該類為一個接口或抽象類。感謝閱讀OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。感謝閱讀-/NewObjectNewObjectANewObjectVjobjectNewObject(JNIEnv*env,jclassclazz,jmethodIDmethodID,...);謝謝閱讀jobjectNewObjectA(JNIEnv*env,jclassclazz,jmethodIDmethodID,jvalue*args);謝謝閱讀jobjectNewObjectV(JNIEnv*env,jclassclazz,jmethodIDmethodID,va_listargs);精品文檔放心下載構(gòu)造新Java對象。方法ID指示應(yīng)調(diào)用的構(gòu)造函數(shù)方法。該ID必須通過調(diào)用GetMethodID()獲得,且調(diào)用時的方法名必須為<init>,而返回類型必須為void(V)。精品文檔放心下載clazz參數(shù)務(wù)必不要引用數(shù)組類。NewObject編程人員應(yīng)將傳遞給構(gòu)造函數(shù)的所有參數(shù)緊跟著放在methodID參數(shù)的后面。精品文檔放心下載NewObject()收到這些參數(shù)后,將把它們傳給編程人員所要調(diào)用的Java方法。精品文檔放心下載NewObjectA編程人員應(yīng)將傳遞給構(gòu)造函數(shù)的所有參數(shù)放在jvalues類型的數(shù)組args中,該數(shù)組緊跟著放在methodID參數(shù)的后面。NewObject()收到數(shù)組中的這些參數(shù)后,將把它們傳給編程人員所要調(diào)用的Java方法。感謝閱讀NewObjectV編程人員應(yīng)將傳遞給構(gòu)造函數(shù)的所有參數(shù)放在va_list類型的參數(shù)args中,該參數(shù)緊跟著放在methodID參數(shù)的后面。NewObject()收到這些參數(shù)后,將把它們傳給編程人員所要調(diào)用的Java方法。感謝閱讀參數(shù):env:JNI接口指針。clazz:Java類對象。-/methodID:構(gòu)造函數(shù)的方法ID。NewObject的其它參數(shù):傳給構(gòu)造函數(shù)的參數(shù)。NewObjectA的其它參數(shù):args:傳給構(gòu)造函數(shù)的參數(shù)數(shù)組。NewObjectV的其它參數(shù):args:傳給構(gòu)造函數(shù)的參數(shù)va_list。返回值:返回Java對象,如果無法構(gòu)造該對象,則返回NULL。感謝閱讀拋出:InstantiationException:如果該類為接口或抽象類。感謝閱讀OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。精品文檔放心下載構(gòu)造函數(shù)拋出的任何異常。GetObjectClassjclassGetObjectClass(JNIEnv*env,jobjectobj);返回對象的類。感謝閱讀參數(shù):env:JNI接口指針。obj:Java對象(不能為NULL)。返回值:返回Java類對象。-/IsInstanceOfjbooleanIsInstanceOf(JNIEnv*env,jobjectobj,jclassclazz);精品文檔放心下載測試對象是否為某個類的實例。參數(shù):env:JNI接口指針。obj:Java對象。clazz:Java類對象。返回值:如果可將obj強(qiáng)制轉(zhuǎn)換為clazz,則返回JNI_TRUE。否則返回JNI_FALSE。NULL對象可強(qiáng)制轉(zhuǎn)換為任何類。感謝閱讀IsSameObjectjbooleanIsSameObject(JNIEnv*env,jobjectref1,jobjectref2);精品文檔放心下載測試兩個引用是否引用同一Java對象。參數(shù):env:JNI接口指針。ref1:Java對象。ref2:Java對象。返回值:如果ref1和ref2引用同一Java對象或均為NULL,則返回JNI_TRUE。否則返回JNI_FALSE。精品文檔放心下載-/訪問對象的域GetFieldIDjfieldIDGetFieldID(JNIEnv*env,jclassclazz,constchar*name,constchar*sig);感謝閱讀返回類的實例(非靜態(tài))域的域ID。該域由其名稱及簽名指定。訪問器函數(shù)的Get<type>Field及Set<type>Field系列使用域ID檢索對象域。精品文檔放心下載GetFieldID()將未初始化的類初始化。GetFieldID()不能用于獲取數(shù)組的長度域。應(yīng)使用GetArrayLength()。謝謝閱讀參數(shù):env:JNI接口指針。clazz:Java類對象。name:0終結(jié)的UTF-8字符串中的域名。謝謝閱讀sig:0終結(jié)的UTF-8字符串中的域簽名。返回值:域ID。如果操作失敗,則返回NULL。拋出:NoSuchFieldError:如果找不到指定的域。謝謝閱讀ExceptionInInitializerError:如果由于異常而導(dǎo)致類初始化程序失敗。感謝閱讀OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。精品文檔放心下載Get<type>Field例程-/NativeTypeGet<type>Field(JNIEnv*env,jobjectobj,jfieldIDfieldID);感謝閱讀該訪問器例程系列返回對象的實例(非靜態(tài))域的值。要訪問的域由通過調(diào)用GetFieldID()而得到的域ID指定。謝謝閱讀下表說明了Get<type>Field例程名及結(jié)果類型。應(yīng)將Get<type>Field中的type替換為域的Java類型(或使用表中的某個實際例程名),然后將NativeType替換為該例程對應(yīng)的本地類型。謝謝閱讀表4-1Get<type>Field訪問器例程系列精品文檔放心下載Get<type>Field例程名 本地類型GetObjectField() jobjectGetBooleanField() jboolean謝謝閱讀GetByteField() jbyteGetCharField() jcharGetShortField() jshortGetIntField() jintGetLongField() jlongGetFloatField() jfloatGetDoubleField() jdouble參數(shù):env:JNI接口指針。obj:Java對象(不能為NULL)。fieldID:有效的域ID。返回值:域的內(nèi)容。Set<type>Field例程voidSet<type>Field(JNIEnv*env,jobjectobj,jfieldIDfieldID,精品文檔放心下載NativeTypevalue);-/該訪問器例程系列設(shè)置對象的實例(非靜態(tài))域的值。要訪問的域由通過調(diào)用SetFieldID()而得到的域ID指定。感謝閱讀下表說明了Set<type>Field例程名及結(jié)果類型。應(yīng)將Set<type>Field中的type替換為域的Java類型(或使用表中的某個實際例程名),然后將NativeType替換為該例程對應(yīng)的本地類型。感謝閱讀表4-2Set<type>Field訪問器例程系列謝謝閱讀Set<type>Field例程名 本地類型SetObjectField() jobjectSetBooleanField() jboolean精品文檔放心下載SetByteField() jbyteSetCharField() jcharSetShortField() jshortSetIntField() jintSetLongField() jlongSetFloatField() jfloatSetDoubleField() jdouble參數(shù):env:JNI接口指針。obj:Java對象(不能為NULL)。fieldID:有效的域ID。value:域的新值。調(diào)用實例方法GetMethodIDjmethodIDGetMethodID(JNIEnv*env,jclassclazz,constchar*name,constchar*sig);謝謝閱讀-/返回類或接口實例(非靜態(tài))方法的方法ID。方法可在某個clazz的超類中定義,也可從clazz繼承。該方法由其名稱和簽名決定。精品文檔放心下載GetMethodID()可使未初始化的類初始化。精品文檔放心下載要獲得構(gòu)造函數(shù)的方法ID,應(yīng)將<init>作為方法名,同時將void(V)作為返回類型。謝謝閱讀參數(shù):env:JNI接口指針。clazz:Java類對象。name:0終結(jié)的UTF-8字符串中的方法名。謝謝閱讀sig:0終結(jié)的UTF-8字符串中的方法簽名。精品文檔放心下載返回值:方法ID,如果找不到指定的方法,則為NULL。拋出:NoSuchMethodError:如果找不到指定方法。精品文檔放心下載ExceptionInInitializerError:如果由于異常而導(dǎo)致類初始化程序失敗。感謝閱讀OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。謝謝閱讀Call<type>Method例程Call<type>MethodA例程Call<type>MethodV例程N(yùn)ativeTypeCall<type>Method(JNIEnv*env,jobjectobj,jmethodIDmethodID,...);謝謝閱讀NativeTypeCall<type>MethodA(JNIEnv*env,jobjectobj,jmethodIDmethodID,jvalue*args);謝謝閱讀-/NativeTypeCall<type>MethodV(JNIEnv*env,jobjectobj,jmethodIDmethodID,va_listargs);感謝閱讀這三個操作的方法用于從本地方法調(diào)用Java實例方法。它們的差別僅在于向其所調(diào)用的方法傳遞參數(shù)時所用的機(jī)制。感謝閱讀這三個操作將根據(jù)所指定的方法ID調(diào)用Java對象的實例(非靜態(tài))方法。參數(shù)methodID必須通過調(diào)用GetMethodID()來獲得。感謝閱讀當(dāng)這些函數(shù)用于調(diào)用私有方法和構(gòu)造函數(shù)時,方法ID必須從obj的真實類派生而來,而不應(yīng)從其某個超類派生。感謝閱讀Call<type>Method例程編程人員應(yīng)將要傳給方法的所有參數(shù)緊跟著放在methodID參數(shù)之后。Call<type>Method例程接受這些參數(shù)并將其傳給編程人員所要調(diào)用的Java方法。感謝閱讀Call<type>MethodA例程編程人員應(yīng)將要傳給方法的所有參數(shù)放在緊跟在methodID參數(shù)之后的jvalues類型數(shù)組args中。Call<type>MethodAroutine接受這些數(shù)組中的參數(shù)并將其傳給編程人員所要調(diào)用的Java方法。感謝閱讀Call<type>MethodV例程編程人員將方法的所有參數(shù)放在緊跟著在methodID參數(shù)之后的va_list類型參數(shù)變量中。Call<type>MethodVroutine接受這些參數(shù)并將其傳給編程人員所要調(diào)用的Java方法。感謝閱讀下表根據(jù)結(jié)果類型說明了各個方法調(diào)用例程。用戶應(yīng)將Call<type>Method中的type替換為所調(diào)用方法的Java類型(或使用表中的實際方法調(diào)用例程名),同時將NativeType替換為該例程相應(yīng)的本地類型。感謝閱讀表4-3實例方法調(diào)用例程本地類Call<type>Method例程名型CallVoidMethod()CallVoidMethodA()CallVoidMethodV() void精品文檔放心下載CallObjectMethod()CallObjectMethodA()謝謝閱讀jobjectCallObjectMethodV()CallBooleanMethod()CallBooleanMethodA()謝謝閱讀jbooleanCallBooleanMethodV()CallByteMethod()CallByteMethodA()CallByteMethodV() jbyte精品文檔放心下載CallCharMethod()CallCharMethodA()CallCharMethodV() jchar感謝閱讀-/CallShortMethod(
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 課題申報參考:賈湖骨笛的實驗音樂考古學(xué)研究
- 2025年度個人消費(fèi)借款信用保證合同范本4篇
- 2025版挖掘機(jī)買賣合同及挖掘機(jī)操作人員培訓(xùn)協(xié)議3篇
- 2025版新媒體人工智能助手研發(fā)與運(yùn)營合同2篇
- 2025版小程序技術(shù)支持授權(quán)協(xié)議范本2篇
- 2025年福州貨車資格證答案
- 2025年度知識產(chǎn)權(quán)代理服務(wù)合同樣本8篇
- 二零二五版毛竹砍伐與林業(yè)碳排放權(quán)交易合同3篇
- 二零二五年度出納風(fēng)險控制擔(dān)保及咨詢合同4篇
- 2025餐飲業(yè)環(huán)保節(jié)能技術(shù)應(yīng)用合作協(xié)議2篇
- 二零二五年度無人駕駛車輛測試合同免責(zé)協(xié)議書
- 2025年湖北華中科技大學(xué)招聘實驗技術(shù)人員52名歷年高頻重點提升(共500題)附帶答案詳解
- 高三日語一輪復(fù)習(xí)助詞「と」的用法課件
- 毛渣采購合同范例
- 無子女離婚協(xié)議書范文百度網(wǎng)盤
- 2023中華護(hù)理學(xué)會團(tuán)體標(biāo)準(zhǔn)-注射相關(guān)感染預(yù)防與控制
- 五年級上冊小數(shù)遞等式計算200道及答案
- 2024年廣東高考政治真題考點分布匯 總- 高考政治一輪復(fù)習(xí)
- 燃?xì)夤艿滥甓葯z驗報告
- GB/T 44052-2024液壓傳動過濾器性能特性的標(biāo)識
- 國際市場營銷環(huán)境案例分析
評論
0/150
提交評論