? 本文原創,轉載請注明出處:http://blog.csdn.NET/qinjuning
?
?
?
?????? ? 最近一段時間,在工作方面比較閑,分配的Bug不是很多,于是好好利用這段時間就著源代碼看了些許模塊,?主要方式
?? 還是賊看賊看代碼,?同時利用燒機的便利,加Log觀看,基本上都能弄個臉熟 。心里想著該寫點什么了?可是水平不夠,再加上
?? 包括很多真正實現地方--中間層,基本上沒看。于是乎,也就不好賣弄了。
?
????? 花了幾天時間研究了下JNI,基本上知道如何使用了。照我的觀點JNI還是不難的,難得只是我們一份嘗試的心。 學習過程中,
??發現關于JNI函數資料真的很少,所謂“工欲善其事,便先利其器”,整理出了這份資料,希望能幫助你克服JNI學習的坎。
?????
????? 主要資料來源: 百度文庫的《JNI常用函數》?。
???? ?同時對其加以了補充 。
???
?
要素? :1、 該函數大全是基于C語言方式的,對于C++方式可以直接轉換 ,例如,對于生成一個jstring類型的方法轉換分別如下:
???????????????????? C編程環境中使用方法為:(*env)?->NewStringUTF(env , "123") ;
??????????????????? C++編程環境中(例如,VC下)則是: env?->NewStringUTF( "123") ;??????????? ?(使用起來更簡單)
?
???????????2、關于下列有些函數中:*isCopy???? 的說明,例如,如下函數:?????????????????????
????????????????????? ???? ?const?char*?GetStringUTFChars(JNIEnv*env, jstring string,?jboolean *isCopy);??
?
????????對第三個參數?jboolean *isCopy說明如下:
?????????????當從JNI函數GetStringUTFChars函數中返回得到字符串B時,如果B是原始字符串Java.lang.String的一份拷貝,
??????則isCopy? 被賦值為JNI_TRUE。如果B是和原始字符串指向的是JVM中的同一份數據,則isCopy? 被賦值為JNI_FALSE。
?????當isCopy? 為JNI_FALSE時,本地代碼絕不能修改字符串的內容,否則JVM中的原始字符串也會被修改,這會打破Java語言
????? 中字符串不可變的規則。
??????????? 通常,我們不必關心JVM是否會返回原始字符串的拷貝,只需要為isCopy傳遞NULL作為參數 。
?????????????????????????????????????????????????????????????????????????????????????????????????????????? ----?????以上內容來自?《JNI編程指南》
?
一、類操作?????????????
? ? ? ? ? ? ? ? ??? ? ? ? ??
? jclass?const jbyte *buf , jsize bufLen); ? ? ? ? ? ? ? ??
? ? ?功能:從原始類數據的緩沖區中加載類。?????????????
? ? ?參數:?env ? ? ? ?JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? ?loader ? ?分派給所定義的類的類加載器。??????????
? ? ? ? ? ? ? ? ?buf ? ? ? ?包含 .class 文件數據的緩沖區。???????????????
? ? ? ? ? ? ? ? ?bufLen ?緩沖區長度。??????????
? ? ?返回值:返回 Java 類對象。如果出錯則返回NULL。 ? ? ? ? ? ?
? ? ?拋出:?ClassFormatError ? ? ?如果類數據指定的類無效。 ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ?ClassCircularityError ?如果類或接口是自身的超類或超接口。 ??????????????
? ? ? ? ? ? ? ? ? ? ? ?OutOfMemoryError ?如果系統內存不足。??????????????????
? ? ? ? ? ? ? ? ??? ? ??
? ?jclass?FindClass?(JNIEnv *env, const char *name);????????????????
?????功能: 該函數用于加載本地定義的類。它將搜索由CLASSPATH 環境變量為具有指定名稱的類所指定的目錄和 zip文件。????????????
?????參數:env ? ?JNI 接口指針。 ? ? ? ? ? ?
??????????????name ?類全名(即包名后跟類名,之間由"/"分隔).如果該名稱以“[(數組簽名字符)打頭,則返回一個數組類。 ? ? ? ??
???? 返回值:返回類對象全名。如果找不到該類,則返回 NULL。 ? ? ? ? ? ? ??
???? 拋出: ??ClassFormatError ? ? ? ? ?如果類數據指定的類無效。 ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ClassCircularityError ? ? ?如果類或接口是自身的超類或超接口。????????????????
? ? ? ? ? ? ? ? ? NoClassDefFoundError ?如果找不到所請求的類或接口的定義。????????????
? ? ? ? ? ? ? ? ? OutOfMemoryError ? ? ? 如果系統內存不足。??????????????????
?
??jclass?GetObjectClass?(JNIEnv *env, jobject obj);?
?????功能:通過對象獲取這個類。該函數比較簡單,唯一注意的是對象不能為NULL,否則獲取的class肯定返回也為NULL。?????
???? 參數: ?env ? JNI 接口指針。 ? ? ? ? ? ?
????????????????obj? ?Java 類對象實例。 ? ??? ??
? ?
??jclass?GetSuperclass?(JNIEnv *env, jclass clazz);??????????
? ? ?功能:獲取父類或者說超類 。?如果 clazz 代表類class而非類 object,則該函數返回由 clazz 所指定的類的超類。 如果 clazz?
? ? ? ? ? ?指定類 object 或代表某個接口,則該函數返回NULL。 ? ? ??? ??
? ? ?參數: ?env ? JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? clazz ?Java 類對象。????????????
? ? ?返回值: ? ?由 clazz 所代表的類的超類或 NULL。 ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ??? ? ? ??
? jboolean?IsAssignableFrom?(JNIEnv *env, jclass clazz1, ?jclass clazz2); ? ? ? ? ??
? ? 功能:確定 clazz1 的對象是否可安全地強制轉換為clazz2。????????????
? ??參數: ?env ?JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? clazz1 第一個類參數。???????????????
? ? ? ? ? ? ? clazz2 第二個類參數。???????????????
? ? 返回值: ?下列某個情況為真時返回 JNI_TRUE: ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? 1、?第一及第二個類參數引用同一個 Java 類。 ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? 2、 第一個類是第二個類的子類。?????????????
? ? ? ? ? ? ? ? ? ? 3、 第二個類是第一個類的某個接口。????
?
? ?
?????????
二、異常操作 ? ? ?? ? ? ? ? ??
? ? ? ? ??? ? ? ? ? ? ??
? jint ?Throw(JNIEnv *env, jthrowable obj);?????????
? ? ??功能:拋出 java.lang.Throwable 對象。?????????????????
? ? ? ?參數:?env ?JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? ?obj ? java.lang.Throwable 對象。?????????
? ? ? ?返回值: ?成功時返回 0,失敗時返回負數。 ? ? ? ? ? ??
? ? ? ?拋出: ? ?java.lang.Throwable 對象 obj。 ? ? ? ? ??
? ??? ? ? ? ? ??
??jint?ThrowNew?(JNIEnv *env , ?jclass clazz, ?const char *message); ? ? ? ? ? ?
? ? ?功能:利用指定類的消息(由 message 指定)構造異常對象并拋出該異常。???????????????
? ? ?參數:?env ? ?JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? clazz ?java.lang.Throwable 的子類。??????????
? ? ? ? ? ? ? ? message ?用于構造java.lang.Throwable對象的消息。???????????
? ? ?返回值:?成功時返回 0,失敗時返回負數。 ? ? ? ? ? ??
? ? ?拋出: ?新構造的 java.lang.Throwable 對象。 ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ???
? jthrowable?ExceptionOccurred?(JNIEnv *env);??????????????
????功能:確定是否某個異常正被拋出。在平臺相關代碼調用 ExceptionClear() 或 Java 代碼處理該異常前,異常將始終保持
??????? 拋出狀態。??????????????????
????參數: ?env ?JNI 接口指針。 ? ? ? ? ? ?
????返回值:?返回正被拋出的異常對象,如果當前無異常被拋出,則返回NULL。 ? ? ? ? ??
? ? ? ? ? ? ? ? ??? ??
?void?ExceptionDescribe?(JNIEnv *env);?????????
????功能:將異常及堆棧的回溯輸出到系統錯誤報告信道(例如 stderr)。該例程可便利調試操作。???????????????
????參數:env ? JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? ????
? void?ExceptionClear?(JNIEnv *env); ? ? ? ? ? ? ? ?
???功能:清除當前拋出的任何異常。如果當前無異常,則此例程不產生任何效果。??????????????????
???參數:?env ? JNI 接口指針。 ? ? ? ? ? ?
? ??? ? ? ? ? ? ??
??void?FatalError?(JNIEnv *env, const char *msg);???????????
???功能:拋出致命錯誤并且不希望虛擬機進行修復。該函數無返回值。?????????????
???參數:??env ? JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ?msg ? 錯誤消息。??????????
?????????????
? ?
?????
?
三、全局及局部引用?????????????
? ? ? ? ? ? ? ? ??? ??
? ?jobject?NewGlobalRef?(JNIEnv *env, jobject obj);?????????
? ? ?功能:創建 obj 參數所引用對象的新全局引用。obj 參數既可以是全局引用,也可以是局部引用。全局引用通過調用?
? ? ? ? ? DeleteGlobalRef() 來顯式撤消。??????????
? ? ?參數:env ? JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? obj ? ?全局或局部引用。?????????????????
? ? ?返回值:?返回全局引用。如果系統內存不足則返回 NULL。 ? ? ? ? ?
? ? ? ? ? ? ? ? ??? ??
? void?DeleteGlobalRef?(JNIEnv *env, jobject globalRef);?????????????????
? ? ?功能: 刪除 globalRef 所指向的全局引用。?????????
? ? ?參數:?env ? ?JNI 接口指針。 ? ? ? ? ? ?
??????????????? globalRef ?全局引用。?????????
? ? ? ? ? ? ? ? ??? ? ? ? ? ??
? void??DeleteLocalRef?(JNIEnv *env, jobject localRef);??????????
?????功能: 刪除 localRef所指向的局部引用。?????????????
?????參數:?env ? JNI 接口指針。 ? ? ? ? ? ?
?????????????????localRef ?局部引用。????????????
?????????????
? ?
????
?
四、對象操作 ? ?? ? ??
? ? ? ? ??
? jobject?AllocObject?(JNIEnv *env, jclass clazz);??????????????
? ? ?功能:分配新 Java 對象而不調用該對象的任何構造函數。返回該對象的引用。clazz 參數務必不要引用數組類。 ? ? ? ? ? ? ??
? ? ?參數:?env ?JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ?clazz ?Java 類對象。????????????
? ? ?返回值:?返回 Java 對象。如果無法構造該對象,則返回NULL。 ? ? ? ? ? ? ? ??
? ? ?拋出:?InstantiationException:如果該類為一個接口或抽象類。 ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ??OutOfMemoryError:如果系統內存不足。??????????????????
????????????????????????
??jobject?NewObject?(JNIEnv *env , ?jclass clazz, ?jmethodID methodID, ...); ? //參數附加在函數后面 ? ? ? ? ? ??
??jobject?NewObjectA?(JNIEnv *env , jclassclazz,??jmethodID methodID, jvalue *args); ? ?//參數以指針形式附加 ? ? ? ? ??
??jobjec tNewObjectV?(JNIEnv *env , jclassclazz,??jmethodID methodID, va_list args); ? ?//參數以"鏈表"形式附加?? ? ? ? ? ?
??功能:構造新 Java 對象。方法 ID指示應調用的構造函數方法。注意:該 ID特指該類class的構造函數ID , 必須通過調用?
??????GetMethodID() 獲得,且調用時的方法名必須為 <init>,而返回類型必須為 void (V)。clazz參數務必不要引用數組類。?
??參數: ?env ?JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? clazz ?Java 類對象。????????????
? ? ? ? ? ? ? methodID 構造函數的方法 ID。???????????????
? ? ?NewObject 的其它參數: ?傳給構造函數的參數,可以為空 。 ? ? ? ? ? ? ? ? ?
? ? ?NewObjectA 的其它參數:?args:傳給構造函數的參數數組。 ? ? ? ? ? ? ?
? ? ?NewObjectV 的其它參數:?args:傳給構造函數的參數 va_list。 ? ? ??
? ? ? ? ? ?
? 返回值:?返回 Java 對象,如果無法構造該對象,則返回NULL。 ? ? ? ? ? ? ? ??
? 拋出: ??InstantiationException ?如果該類為接口或抽象類。 ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? OutOfMemoryError ? 如果系統內存不足。??????????????????
? ? ? ? ? ? ? 構造函數拋出的任何異常。??????????????????
? ? ? ? ? ? ? ? ??? ? ? ? ? ? ?
? jclass?GetObjectClass?(JNIEnv *env, jobject obj);?????????
? ?功能:返回對象的類。?????????????
? ?參數:?env ?JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ?? ?obj ?Java 對象(不能為 NULL)。???????????????
? ?返回值:?返回 Java 類對象。 ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ??? ? ? ??
?jboolean?IsInstanceOf?(JNIEnv *env, jobject obj,?jclass clazz); ? ? ? ? ? ??
???功能:測試對象是否為某個類的實例。??????????????????
???參數:??env ?JNI 接口指針。 ? ? ? ? ? ?
???????????????obj ?Java 對象。???????????
???????????????clazz Java 類對象。????????????
???返回值:如果可將 obj 強制轉換為 clazz,則返回 JNI_TRUE。否則返回 JNI_FALSE。NULL 對象可強制轉換為任何類。 ? ? ? ? ??
? ? ? ? ? ? ? ? ??? ? ? ? ?
?jbooleanIsSameObject?(JNIEnv *env, jobjectref1,?jobject ref2); ? ? ? ? ? ?
? ? 功能:測試兩個引用是否引用同一 Java 對象。?????????
? ? 參數: ?env ?JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ????? ?ref1 ?Java 對象。??????????????????
? ? ? ? ????? ?ref2 ? Java 對象。??????????????????
? ? 返回值:?如果 ref1 和 ref2 引用同一 Java 對象或均為 NULL,則返回 JNI_TRUE。否則返回 JNI_FALSE。 ? ? ? ??
????????
? ?
????
??????????????????
五、?字符串操作?????????????
? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ??
? jstring??NewString?(JNIEnv *env, const jchar *unicodeChars, ??jsize len); ? ? ? ??
??? 功能:利用 Unicode 字符數組構造新的 java.lang.String 對象。???????????????
??? 參數: ??env:JNI 接口指針。 ? ? ? ? ? ?
?????????????????unicodeChars:指向 Unicode 字符串的指針。?????????
?????????????????len:Unicode 字符串的長度。?????????????
??? 返回值:?Java 字符串對象。如果無法構造該字符串,則為NULL。 ? ? ? ? ? ??
????拋出:?OutOfMemoryError:如果系統內存不足。 ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ??? ? ? ? ? ??
?jsize??GetStringLength?(JNIEnv *env, jstring string);????????????
? ? 功能:返回 Java 字符串的長度(Unicode 字符數)。?????????????????
? ? 參數: ?env:JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? string:Java 字符串對象。??????????
? ? 返回值:?Java 字符串的長度。 ? ? ? ? ? ?
? ? ? ? ? ? ? ??? ? ? ? ? ? ??
? const??jchar *??GetStringChars?(JNIEnv*env, jstring string, ?jboolean *isCopy); ? ? ? ? ??
? ?功能:返回指向字符串的 Unicode 字符數組的指針。該指針在調用 ReleaseStringchars() 前一直有效。??????????
? ? ? ? ?如果 isCopy 非空,則在復制完成后將 *isCopy 設為 JNI_TRUE。如果沒有復制,則設為JNI_FALSE。 ?
? ?參數: ??env:JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? string:Java 字符串對象。??????????
? ? ? ? ? ? ? ??isCopy:指向布爾值的指針。???????????????
?? 返回值: ??指向 Unicode 字符串的指針,如果操作失敗,則返回NULL。 ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ??
?void??ReleaseStringChars?(JNIEnv *env, jstring string, ?const jchar *chars); ? ? ? ? ? ? ? ? ?
???功能:通知虛擬機平臺相關代碼無需再訪問 chars。參數chars 是一個指針,可通過 GetStringChars() 從 string 獲得。 ? ?
???參數:?env:JNI 接口指針。 ? ? ? ? ? ?
????????????? string:Java 字符串對象。??????????
????????????? chars:指向 Unicode 字符串的指針。???????????????
? ? ? ? ? ? ? ? ?? ? ? ?
?jstring??NewStringUTF?(JNIEnv *env, const char *bytes);????????????
? ?功能:利用 UTF-8 字符數組構造新 java.lang.String 對象。???????????????
? ?參數:?env:JNI 接口指針。如果無法構造該字符串,則為 NULL。 ? ? ? ??
????????????? bytes:指向 UTF-8 字符串的指針。??????????
? ?返回值:Java 字符串對象。如果無法構造該字符串,則為NULL。 ? ? ? ? ? ??
? ?拋出: ?OutOfMemoryError:如果系統內存不足。 ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ??? ? ? ? ??
?jsize??GetStringUTFLength?(JNIEnv *env, jstring string);??????????????
? ?功能:以字節為單位返回字符串的 UTF-8 長度。 ? ? ? ? ? ? ? ?
?? 參數:?? env:JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ?string:Java 字符串對象。??????????
? ?返回值: ?返回字符串的 UTF-8
?const?char*?GetStringUTFChars?(JNIEnv*env, jstring string,?jboolean *isCopy); ? ? ? ? ??
? ?功能:返回指向字符串的 UTF-8 字符數組的指針。該數組在被ReleaseStringUTFChars() 釋放前將一直有效。 ? ?如果 isCopy?
? ? ? 不是 NULL,*isCopy 在復制完成后即被設為 JNI_TRUE。如果未復制,則設為 JNI_FALSE。 ? ? ? ? ? ??
? ?參數: ?env:JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ??string:Java 字符串對象。??????????
? ? ? ? ? ? ? isCopy:指向布爾值的指針。???????????????
? ?返回值: ?指向 UTF-8 字符串的指針。如果操作失敗,則為 NULL。 ? ? ? ? ? ??
? ? ? ? ? ? ? ? ??? ? ? ? ??
? void??ReleaseStringUTFChars?(JNIEnv *env, jstring string, ?const char *utf); ? ? ? ? ? ? ??
? ?功能:通知虛擬機平臺相關代碼無需再訪問 utf。utf 參數是一個指針,可利用 GetStringUTFChars() 獲得。 ? ? ? ? ? ? ? ? ?
?? 參數: ? env:JNI 接口指針。 ? ? ? ? ? ?
?????????????? string:Java 字符串對象。??????????
? ? ? ? ? ? ?? utf:指向 UTF-8 字符串的指針。???????????????
?
?
? ?
?????????
六、數組操作 ? ? ? ? ? ? ? ??? ? ? ? ?
?jsize?GetArrayLength?(JNIEnv *env, jarray array);?????????????????
? ?功能:返回數組中的元素數。??????????????????
? ?參數: ?env:JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? array:Java 數組對象。????????????????
? ?返回值:?數組的長度。 ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ??? ? ? ? ? ?
?jarray?NewObjectArray?(JNIEnv *env, jsize length, ?jclass elementClass, jobject initialElement); ? ? ? ? ??
???功能:構造新的數組,它將保存類 elementClass 中的對象。所有元素初始值均設為 initialElement。???????????????
???參數:?env:JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ?length:數組大小。???????????????
? ? ? ? ? ? ?elementClass:數組元素類。???????????????
? ? ? ? ? ? ?initialElement:初始值。 ? ?可以為NULL 。 ? ? ? ? ??
? ?返回值:Java 數組對象。如果無法構造數組,則為 NULL。 ? ? ? ? ? ? ? ? ?
? ?拋出: ?OutOfMemoryError:如果系統內存不足。 ? ? ? ? ? ? ? ? ?
? ?
? ?說明: 使用該函數時,為了便于易操作性,我們一般可以用jobjectArray數組類型或得返回值,例如:
? ? ? ? ? ? ? ? ?jobjectArray objArray = env->NewObjectArray ( );
? ? ? ? ? ? ? ? ?//操作該對象
? ? ? ? ? ? ? ? ?env->GetObjectArrayElement?(objArray, 0);//獲得該object數組在索引0處的值 ,(可以強制轉換類型).
?jobject ?GetObjectArrayElement?(JNIEnv *env, ??jobjectArray array, jsize index); ? ? ? ? ? ? ? ?
? ?功能:返回 Object 數組的元素。??????????
? ?參數:? ?env:JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ?? ?array:Java 數組。????????????????
? ? ? ? ? ? ?? ?index:數組下標。?????????????????
? ?返回值:?Java 對象。 ? ? ? ? ? ?
? ?拋出:?ArrayIndexOutOfBoundsException:如果 index 不是數組中的有效下標。 ? ? ? ? ? ??
? ? ? ? ? ? ? ? ??
? void??SetObjectArrayElement?(JNIEnv *env, jobjectArray array, ?jsize index, jobject value); ? ? ? ? ? ? ? ?
? ?功能:設置 Object 數組的元素。??????????
? ?參數: ?env:JNI 接口指針。 ? ? ? ? ? ?
????????????? array:Java 數組。????????????????
? ? ? ? ? ?? ? index:數組下標。?????????????????
? ? ? ? ? ?? ? value:新值。?????????????????
? ?拋出:?ArrayIndexOutOfBoundsException:如果 index 不是數組中的有效下標。 ? ? ? ? ? ??
? ? ? ? ? ? ? ArrayStoreException:如果 value 的類不是數組元素類的子類。???????????
??????????????????????
?
????New<PrimitiveType>Array方法類型??????
?????????New<PrimitiveType>Array?(JNIEnv *env,?ArrayType array, jboolean*isCopy); ? ? ? ? ? ? ? ? ?
?
? ? ?說明: 用于構造新基本類型數組對象的一系列操作。下表說明了特定的基本類型數組構造函數。用戶應把
? ? New<PrimitiveType>Array 替換為某個實際的基本類型數組構造函數例程名(見下表),然后將 ArrayType替換為
該例程相應的數組類型。
?????參數: ?env : JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? ?length:數組長度。???????????????
?????返回值: ?Java 數組。如果無法構造該數組,則為 NULL。
?????? ? ?
? ? ? ? ? ? New<PrimitiveType>Array?方法組???????????????數組類型????????
? ? ? ? ? ? ? ? ? NewBooleanArray() ? ? ? ? ? ? ? ? ? ? ? ? ? ?jbooleanArray?
? ? ? ? ? ? ? ? ? NewByteArray() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jbyteArray???????
? ? ? ? ? ? ? ? ? NewCharArray() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? jcharArray???????
? ? ? ? ? ? ? ? ? NewShortArray() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jshortArray??????
? ? ? ? ? ? ? ? ? NewIntArray() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jintArray?
? ? ? ? ? ? ? ? ? NewLongArray() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? jlongArray????????
? ? ? ? ? ? ? ? ? NewFloatArray() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? jfloatArray???????
? ? ? ? ? ? ? ? ? NewDoubleArray()???????????????????????????? jdoubleArray???
?????????????????
??????????????????
?Get<PrimitiveType>ArrayElements?方法類型???????
?
? NativeType?*Get<PrimitiveType>ArrayElements?(JNIEnv *env,?ArrayType array, jboolean*isCopy); ? ? ? ? ? ? ? ? ?
? ?說明:一組返回基本類型數組體的函數。結果在調用相應的 Release<PrimitiveType>ArrayElements()函數前將一直有效。
? ? ?由于返回的數組可能是 Java 數組的副本,因此對返回數組的更改不必在基本類型數組中反映出來,直到調用了
? ? ?Release<PrimitiveType>ArrayElements()。?如果 isCopy 不是 NULL,*isCopy 在復制完成后即被設為 JNI_TRUE。如果
? ? ?未復制,則設為 JNI_FALSE。 ? ? ? ? ?
? 使用說明: ??
? ? ? 將 Get<PrimitiveType>ArrayElements 替換為表中某個實際的基本類型元素訪問器例程名。?????????????
? ? ? 將 ArrayType 替換為對應的數組類型。?????????????
? ? ? 將 NativeType 替換為該例程對應的本地類型。???????????????
????參數:???env:JNI 接口指針。 ? ? ? ? ? ?
??????????????? array:Java 字符串對象。???????????
? ? ? ? ? ? ? ? isCopy:指向布爾值的指針。???????????????
? ? 返回值:????返回指向數組元素的指針,如果操作失敗,則為 NULL。 ? ? ? ? ?
?????????????
? ?? 不管布爾數組在 Java 虛擬機中如何表示,GetBooleanArrayElements() 將始終返回一個 jbooleans 類型的指針,其中每一
字節代表一個元素(開包表示)。內存中將確保所有其它類型。
? ? ? ????
? ? ? ? ? ? Get<PrimitiveType>ArrayElements 例程 ? ? ? ? 數組類型 ? ? ? ? ? ? ? ? ?本地類型
? ? ? ? ? ? ? ? ? GetBooleanArrayElements() ? ? ? ? ? ? ? ? ? jbooleanArray ? ? ? ? ? ?jboolean
? ? ? ? ? ? ? ? ? GetByteArrayElements() ? ? ? ? ? ? ? ? ? ? ?? ?jbyteArray ? ? ? ? ? ? ? ? ?jbyte
? ? ? ? ? ? ? ? ? GetCharArrayElements() ? ? ? ? ? ? ? ? ? ? ? ?jcharArray ? ? ? ? ? ? ? ? ?jchar
? ? ? ? ? ? ? ? ? GetShortArrayElements() ? ? ? ? ? ? ? ? ?? ? ?jshortArray ? ? ? ? ? ? ? ? jshort
? ? ? ? ? ? ? ? ? GetIntArrayElements() ? ? ? ? ? ? ? ? ? ? ? ? ? jintArray ? ? ? ? ? ? ? ? ? ? jint
? ? ? ? ? ? ? ? ? GetLongArrayElements() ? ? ? ? ? ? ? ? ? ? ? ?jlongArray ? ? ? ? ? ? ? ? ?jlong
? ? ? ? ? ? ? ? ? GetFloatArrayElements() ? ? ? ? ? ? ? ? ? ? ? ?jfloatArray ? ? ? ? ? ? ? ? ?jfloat
? ? ? ? ? ? ? ? ? GetDoubleArrayElements() ? ? ? ? ? ? ? ? ?? ?jdoubleArray ? ? ? ? ? ? ?jdouble
??????
??????????????????
???? ?Release<PrimitiveType>ArrayElements?方法類型????????????????
?
??void??Release<PrimitiveType>ArrayElements?(JNIEnv *env,?ArrayType array, NativeType *elems,jint mode);????????????
???? 功能:通知虛擬機平臺相關代碼無需再訪問 elems 的一組函數。elems 參數是一個通過使用對應的
??????? Get<PrimitiveType>ArrayElements() 函數由 array 導出的指針。必要時,該函數將把對 elems 的修改復制回基本
??????? 類型數組。mode參數將提供有關如何釋放數組緩沖區的信息。如果elems 不是 array 中數組元素的副本,mode將無效。
??????? 否則,mode 將具有下表所述的功能:?????????????
??????????????????????? 模式???????????????????????????????????????? 動作????????
???????????????????????? 0??????????????????????????? 復制回內容并釋放elems 緩沖區??????
?????????????????? JNI_COMMIT?????????????? 復制回內容但不釋放elems 緩沖區??
?????????????????? JNI_ABORT??????????????? ?? 釋放緩沖區但不復制回變化????????
?????? 多數情況下,編程人員將把“0”傳給 mode 參數以確保固定的數組和復制的數組保持一致。其它選項可以使編程人員進一步
?? 控制內存管理,但使用時務必慎重。?????????????
??? ?使用說明:
???????? 將 ArrayType 替換為對應的數組類型。?????????????
???????? 將 NativeType 替換為該例程對應的本地類型。???????????????
????
?? 參數:?env:JNI 接口指針。????????????
?????????????array:Java 數組對象。????????????????
?????????????elems:指向數組元素的指針。???????????
?????????????mode:釋放模式。??????
?
?????????Release<PrimitiveType>ArrayElements?方法組???????? 數組類型???????????? 本地類型
????????????? ReleaseBooleanArrayElements()??????????????? ???? ?jbooleanArray?????? jboolean
??????????????ReleaseByteArrayElements()?????????????????????? ??? jbyteArray????????????? jbyte
??????????????ReleaseCharArrayElements()??????????????????????? ??jcharArray???????????? ?jchar
????????????? ReleaseShortArrayElements()?????????????????????? ? jshortArray??????????? ?jshort
????????????? ReleaseIntArrayElements()??????????????????????????? ?jintArray????????????? ? ?jint
??????????????ReleaseLongArrayElements()???????????????????????jlongArray???????????? jlong
??????????? ? ReleaseFloatArrayElements()???????????????????????jfloatArray????????? ??jfloat
????????????? ReleaseDoubleArrayElements()?????????????????? jdoubleArray??????? ?jdouble
??????????
??????????????????
????Get<PrimitiveType>ArrayRegion?方法類型??????????
?
??void??Get<PrimitiveType>ArrayRegion?(JNIEnv *env, ArrayType array,??jsize start, jsize len, NativeType *buf);????????????
?? ?功能:將基本類型數組某一區域復制到緩沖區中的一組函數。????????????????????
??????使用說明:????????
?????????????? 將 Get<PrimitiveType>ArrayRegion 替換為下表的某個實際基本類型元素訪問器例程名。
????????????? ?將 ArrayType 替換為對應的數組類型。?????????????
?????????????? 將 NativeType 替換為該例程對應的本地類型。?????
?? 參數:?????env:JNI 接口指針。????????????
???????????????? array:Java 指針。????????????????
???????????????? start:起始下標。??????????????????
???????????????? len:要復制的元素數。?????????????????
???????????????? buf:目的緩沖區。????????????????
?? 拋出:??ArrayIndexOutOfBoundsException:如果區域中的某個下標無效。??
??????????
?? 方法族如下:????????????????????? ????
????????????????????Get<PrimitiveType>ArrayRegion方法?????????? 數組類型???????????? 本地類型
????????????????????????GetBooleanArrayRegion()??????????????????????????jbooleanArray??? ?jboolean
??????????????????????? GetByteArrayRegion()????????????????????????????? ? jbyteArray?????????? jbyte
??????????????????????? GetCharArrayRegion()???????????????????????????? ? jcharArray?????????? jchar
??????????????????????? GetShortArrayRegion()???????????????????????????? ?jshortArray????????? jhort
????????????????????????GetIntArrayRegion()????????????????????????????????? jintArray??????????????jint
??????????????????????? GetLongArrayRegion()????????????????????????????? ?jlongArray??????? ? jlong
????????????????????????GetFloatArrayRegion()????????????????????????????? ?jfloatArray??????? ?jloat
????????????????????????GetDoubleArrayRegion()????????????????????????? ?jdoubleArray??? jdouble
??????????
??????????????????
??????? Set<PrimitiveType>ArrayRegion?方法類型??????????
?
?void??Set<PrimitiveType>ArrayRegion?(JNIEnv *env, ArrayType array,???jsize start, jsize len, NativeType *buf);????????????
??? 功能:將基本類型數組的某一區域從緩沖區中復制回來的一組函數。?????????????
????????使用說明:??將 Set<PrimitiveType>ArrayRegion 替換為表中的實際基本類型元素訪問器例程名。??????????
??????????????????????????將 ArrayType 替換為對應的數組類型。?????????????
??????????????????????????將 NativeType 替換為該例程對應的本地類型。???????????????
????參數:?env:JNI 接口指針。????????????
??????????????array:?Java 數組。??????????????
??????????????start:起始下標。??????????????????
??????????????len:要復制的元素數。?????????????????
??????????????buf:源緩沖區。????????????
????拋出:?ArrayIndexOutOfBoundsException:如果區域中的某個下標無效。?
? ????
????????????????? Set<PrimitiveType>ArrayRegion?方法族??????????? 數組類型??????????? ?本地類型
??????????????????????? SetBooleanArrayRegion()??????????????????????? ? jbooleanArray???? jboolean
??????????????????????? SetByteArrayRegion()???????????????????????????? ?? jbyteArray???????????jbyte
????????????????????????SetCharArrayRegion()???????????????????????????? ??jcharArray???????? ??jchar
??????????????????????? SetShortArrayRegion()??????????????????????????? ? jshortArray???????? ?jshort
??????????????????????? SetIntArrayRegion()??????????????????????????????????jintArray????????????? jint
????????????????????????SetLongArrayRegion()????????????????????????????? ?jlongArray??????? ?? jlong
????????????????????????SetFloatArrayRegion()?????????????????????????????? jfloatArray????????? ?jfloat
????????????????????????SetDoubleArrayRegion()??????????????????????????? jdoubleArray????? jdouble
???????
? ?
?
?
?
?六、訪問對象的屬性和方法??????????????????
???
1、實例屬性的訪問
???????????????????????????
??jfieldID??GetFieldID?(JNIEnv *env, jclass clazz,?const char *name, const char *sig);????????????????
?? 功能:返回類的實例(非靜態)域的屬性 ID。該域由其名稱及簽名指定。訪問器函數的Get<type>Field 及 Set<type>Field
??????? 系列使用域 ID 檢索對象域。GetFieldID() 不能用于獲取數組的長度域。應使用GetArrayLength()。??????????
?? 參數:??env:JNI 接口指針。????????????
???????????????clazz:Java 類對象。????????????
?????????????? name: 該屬性的Name名稱????????????????
???????????????sig:?? 該屬性的域簽名。???????????????
?? 返回值:屬性ID。如果操作失敗,則返回NULL。??????????????
?? 拋出:?NoSuchFieldError:如果找不到指定的域。??????????????????
????????????? ExceptionInInitializerError:如果由于異常而導致類初始化程序失敗。??????????
????????????? OutOfMemoryError:如果系統內存不足。?????????????????
???????????????
?? Get<type>Field 例程???????????????
?
?? NativeType??Get<type>Field?(JNIEnv*env, jobject obj, jfieldID fieldID);????????????????
??? 功能:該訪問器例程系列返回對象的實例(非靜態)域的值。要訪問的域由通過調用GetFieldID() 而得到的域 ID 指定。???????????
????參數:???env:JNI 接口指針。????????????
???????????????? obj:Java 對象(不能為 NULL)。???????????????
???????????????? fieldID:有效的域 ID。?????????????????
?? ?返回值:???屬性的內容。??????
??? ?????Get<type>Field 例程名??????? 本地類型????????
?????????????? GetObjectField()???????????????? ?jobject?????
???????????????GetBooleanField()???????????? ??jboolean??
?????????????? GetByteField()??????????????????? ?jbyte????????
?????????????? GetCharField()???????????????????? jchar????????
?????????????? GetShortField()????????????????? ? jshort???????
?????????????? GetIntField()??????????????????????? jint??
?????????????? GetLongField()????????????????????jlong?????????
?????????????? GetFloatField()???????????????? ?? jfloat????????
???????????????GetDoubleField()????? jdouble????
?
???Set<type>Field?方法族?
????????
? void??Set<type>Field?(JNIEnv *env, jobject obj, jfieldID fieldID,??NativeType value);???????????
??功能: 該訪問器例程系列設置對象的實例(非靜態)屬性的值。要訪問的屬性由通過調用SetFieldID() 而得到的屬性 ID指定。
?
???參數:??env:JNI 接口指針。????????????
?????????????? obj:Java 對象(不能為 NULL)。???????????????
????????????? fieldID:有效的域 ID。???????? ????????
??????????????value:域的新值。???
??? ??方法族?如下:???????????????? ????
?????????????? Set<type>Field?方法族??????????? 本地類型????????
????????????????? SetObjectField()????????????????? ??jobject?????
????????????????? SetBooleanField()????????????? ?? ?jboolean??
??????????????????SetByteField()???????????????????? ? jbyte????????
????????????????? SetCharField()??????????????????????jchar????????
????????????????? SetShortField()??????????????????? ?jshort???????
????????????????? SetIntField()??????????????????????? ?jint??
??????????????????SetLongField()????????????????????? jlong?????????
????????????????? SetFloatField()????????????????????? jfloat????????
????????????????? SetDoubleField()????????????????? jdouble????
?
?2、靜態屬性的訪問 :也存在相同的方法,
?
????? ??jfieldID??GetStaticFieldID?(JNIEnv *env,jclass clazz,?const char *name, const char *sig);?????
???? ??NativeType??GetStatic<type>Field?(JNIEnv*env,jclass classzz , jfieldID fieldID);???????????
?????????? ?void??SetStatic<type>Field?(JNIEnv *env,jclassclasszz, jfieldID fieldID,??NativeType value);???????????
???
?? 它們與實例屬性的唯一區別在于第二個參數jclass classzz代表的是類引用,而不是類實例。
????????
?3、調用實例方法?
??????
? ?jmethodID?GetMethodID(JNIEnv *env, jclass clazz, ? ?const char *name, const char *sig); ? ? ? ? ? ? ? ?
??? 功能:返回類或接口實例(非靜態)方法的方法 ID。方法可在某個 clazz 的超類中定義,也可從 clazz 繼承。該方法由其名稱
? ? ? ? ?和簽名決定。?GetMethodID() 可使未初始化的類初始化。要獲得構造函數的方法 ID,應將 <init> 作為方法名,同時將?
? ? ? ? ?void (V) 作為返回類型。 ? ? ? ? ?
? ? 參數: ?env:JNI 接口指針。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? clazz:Java 類對象。????????????
? ? ? ? ? ? ? ? name:方法名。??????????
? ? ? ? ? ? ? ? sig:方法的簽名。???????????
??? 返回值:?方法 ID,如果找不到指定的方法,則為 NULL。 ? ? ? ? ? ??
??? 拋出: ? ?NoSuchMethodError:如果找不到指定方法。 ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ExceptionInInitializerError:如果由于異常而導致類初始化程序失敗。??????????
? ? ? ? ? ? ? ? ? OutOfMemoryError:如果系統內存不足。??????????????????
??????????????????
? Call<type>Method 例程 ?、Call<type>MethodA 例程 ?、Call<type>MethodV 例程?
??????????????
? NativeType?Call<type>Method?(JNIEnv*en v, ?jobject obj ,?jmethodID methodID, ...);???? //參數附加在函數后面,??????????????
? NativeType?Call<type>MethodA?(JNIEnv *env, jobject obj,?jmethodID methodID, jvalue *args);??//參數以指針形式附加 ?
??NativeType?Call<type>MethodV?(JNIEnv *env, jobject obj,jmethodID methodID, va_list args);?//參數以"鏈表"形式附加
?????
??說明:這三個操作的方法用于從本地方法調用Java 實例方法。它們的差別僅在于向其所調用的方法傳遞參數時所用的機制。 ??
??????這三個操作將根據所指定的方法 ID 調用 Java 對象的實例(非靜態)方法。參數 methodID 必須通過調用 GetMethodID()?
??????來獲得。當這些函數用于調用私有方法和構造函數時,方法 ID 必須從obj 的真實類派生而來,而不應從其某個超類派生。
????? 當然,附加參數可以為空 。
??參數: ?env:JNI 接口指針。 ? ? ? ? ? ?
???????????? obj:Java 對象。???????????
???????????? methodID:方法 ID。 ? ? ? ? ??? ? ? ?
? 返回值: 返回調用 Java 方法的結果。 ? ? ? ? ? ? ?
??拋出: ?執行 Java 方法時拋出的異常。 ? ?
?????????????
?
? ? ?
? ?下表根據結果類型說明了各個方法類型。用戶應將Call<type>Method 中的 type 替換為所調用方法的Java 類型(或使用表
?中的實際方法名),同時將 NativeType 替換為該方法相應的本地類型。省略掉了其他兩種類型。?
?
???????????Java層返回值 ? ? ? ? ? ? ? ?? 方法族 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?本地返回類型NativeType
????????? ?返回值為void : ? ? ???? CallVoidMethod( ) ? A?/ V?????????????????????????????? (無)
? ???????? 返回值為引用類型: ?? ?CallObjectMethod( ) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jobect
? ???????? 返回值為boolean :?? ?CallBooleanMethod ( ) ? ? ? ? ? ? ? ? ? ? ? ? ? jboolean
??????? ? ?返回值為byte : ? ? ??? ?CallByteMethod( ) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jbyte
???????? ??返回值為char ?: ? ? ?? ?CallCharMethod( ) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? jchar
??????? ?? 返回值為short? ? ? ? ??? ?CallShortMethod( ) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jshort???????
????????? ?返回值為int? ?:?? ? ??? ?CallIntMethod( )?????????????????????????????????????jint??
????????? ?返回值為long:? ? ? ?? ?CallLongMethod() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? jlong?????????
? ???????? 返回值為float : ? ? ?? ?CallFloatMethod() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? jfloat????????
? ???????? 返回值為double:??? ? CallDoubleMethod() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jdouble????
?
?
?4、調用靜態方法:也存在如下方法群,
?
????? ??jfieldID? ?GetStaticMethodID?(JNIEnv *env,jclass clazz,?const char *name, const char *sig);?????
???? ??NativeType??Call<type>Method?(JNIEnv*env,jclass classzz , jfieldID fieldID);???????????
???????
?? 它們與于實例方法的唯一區別在于第二個參數jclass classzz代表的是類引用,而不是類實例。
?????
??
?
七、注冊本地方法??????????????????
????????????????
??jint??RegisterNatives?(JNIEnv *env, jclass clazz,?const JNINativeMethod *methods,??? jint? nMethods);???????????????
?? 功能:向 clazz 參數指定的類注冊本地方法。methods 參數將指定 JNINativeMethod 結構的數組,其中包含本地方法的名稱、
??? 簽名和函數指針。nMethods 參數將指定數組中的本地方法數。JNINativeMethod 結構定義如下所示:????????????
???????? typedef struct {???????????????????????
????????? ? ? ?char *name;??????????
?????????? ? ? char *signature;???????????????
????????? ????void *fnPtr;???????????????
?????????} JNINativeMethod;??????????????????
?????函數指針通常必須有下列簽名:??????????????????????????????????
??????????? ??ReturnType (*fnPtr)(JNIEnv *env, jobject objectOrClass, ...);??????????????????
??????????????????
?? 參數:?env:JNI 接口指針。????????????
?????????? ?? clazz:Java 類對象。????????????
????????? ???methods:類中本地方法和具體實現方法的映射指針。???????????????
?????????? ??nMethods:類中的本地方法數。?????????????????
? ?返回值:??成功時返回 "0";失敗時返回負數。?????????
?? 拋出:??NoSuchMethodError:如果找不到指定的方法或方法不是本地方法。????????????
??????????????????
?jint??UnregisterNatives?(JNIEnv *env, jclass clazz);??????????????
??功能: 取消注冊類的本地方法。類將返回到鏈接或注冊了本地方法函數前的狀態。??????該函數不應在常規平臺相關代碼中使用。
??????? 相反,它可以為某些程序提供一種重新加載和重新鏈接本地庫的途徑。?????????????
? 參數:??env:JNI 接口指針。????????????
?????????? ? clazz:Java 類對象。????????????
? 返回值:?成功時返回“0”;失敗時返回負數。??????????????????
?
?
?
?
????其實,JNI方面的書籍還是比較少的,建議大家看看《JNI編程指南》,算的上個入門書籍吧,指望你能耐心點看。
?
???? 下一篇,我會繼續整理JNI的基礎知識,包括類型映射、域簽名等;