Android JNI函數(shù)

0.要素
1.類操作
2.異常操作
3.全局及局部引用
4.對(duì)象操作
5.字符串操作
6.數(shù)組操作
7.訪問(wèn)對(duì)象的屬性和方法
7.1 實(shí)例屬性的訪問(wèn)
7.2 靜態(tài)屬性的訪問(wèn)
7.3 調(diào)用實(shí)例方法
7.4 調(diào)用靜態(tài)方法(也存在如下方法群)
8.注冊(cè)本地方法

0.要素
1.該函數(shù)大全是基于 C 語(yǔ)言方式的联贩,對(duì)于 C++方式可以直接轉(zhuǎn)換漫仆,
例如:對(duì)于生成一個(gè) jstring 類型的方法轉(zhuǎn)換分別如下:
C 編程環(huán)境中使用方法為:(env)->NewStringUTF(env ,"123");
C++編程環(huán)境中(例如,VC 下)則是:env->NewStringUTF( "123");
2.關(guān)于下列有些函數(shù)中:
isCopy 的說(shuō)明泪幌,
例如盲厌,如下函數(shù):
const char* GetStringUTFChars(JNIEnv*env, jstring string,
jboolean *isCopy);

對(duì)第三個(gè)參數(shù) jboolean *isCopy 說(shuō)明如下:
當(dāng)從 JNI 函數(shù) GetStringUTFChars 函數(shù)中返回得到字符串 B 時(shí),如果 B 是原始字
符串 Java.lang.String 的一份拷貝祸泪,則 isCopy 被賦值為 JNI_TRUE吗浩。如果 B 是和原始
字符串指向的是 JVM 中的同一份數(shù)據(jù),則 isCopy 被賦值為 JNI_FALSE没隘。當(dāng) isCopy 為
JNI_FALSE 時(shí)懂扼,本地代碼絕不能修改字符串的內(nèi)容,否則 JVM 中的原始字符串也會(huì)被
修改右蒲,這會(huì)打破 Java 語(yǔ)言中字符串不可變的規(guī)則阀湿。
通常,我們不必關(guān)心 JVM 是否會(huì)返回原始字符串的拷貝瑰妄,只需要為 isCopy 傳遞
NULL 作為參數(shù)陷嘴。

----以上內(nèi)容來(lái)自 《JNI 編程指南》

1.類操作
(1)從原始類數(shù)據(jù)的緩沖區(qū)中加載類
jclass DefineClass (JNIEnv* env,
jobject loader,
const jbyte* buf,
jsize bufLen);
參數(shù):env:JNI 接口指針。
loade:分派給所定義的類的類加載器翰撑。
buf:包含.class 文件數(shù)據(jù)的緩沖區(qū)罩旋。
bufLen:緩沖區(qū)長(zhǎng)度。
返回值:返回 Java 類對(duì)象眶诈。如果出錯(cuò)則返回 NULL涨醋。
拋出異常:
ClassFormatError:如果類數(shù)據(jù)指定的類無(wú)效。
ClassCircularityError:如果類或接口是自身的超類或超接口逝撬。
OutOfMemoryError:如果系統(tǒng)內(nèi)存不足浴骂。

(2)該函數(shù)用于加載本地定義的類。
它將搜索由 CLASSPATH 環(huán)境變量為具有指定名稱的類所指定的目錄和 zip 文件宪潮。
jclass FindClass (JNIEnv* env,
const char* name);
參數(shù):
env:JNI 接口指針溯警。
name:類全名(即包名后跟類名,之間由"/"分隔).如果該名稱以“[(數(shù)組
簽名字符開頭)狡相,則返回一個(gè)數(shù)組類梯轻。
返回值:返回類對(duì)象全名。如果找不到該類尽棕,則返回 NULL喳挑。
拋出異常:
ClassFormatError:如果類數(shù)據(jù)指定的類無(wú)效。
ClassCircularityError:如果類或接口是自身的超類或超接口滔悉。
NoClassDefFoundError:如果找不到所請(qǐng)求的類或接口的定義伊诵。
OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。
示例:
// 獲取數(shù)組類對(duì)象
jclass intArrayClazz = env->FindClass("[I");

(3)通過(guò)對(duì)象獲取這個(gè)類
該函數(shù)比較簡(jiǎn)單回官,對(duì)象不能為 NULL曹宴,否則獲取的 class 返回也為 NULL。
jclass GetObjectClass ( JNIEnv* env,
jobject obj);
參數(shù):
env:JNI 接口指針歉提。
obj:Java 類對(duì)象實(shí)例笛坦。
返回值:由 class 所代表的類的超類或 NULL。
示例:
jobject stu; //該變量由外部傳入唯袄,實(shí)際上為 Student 類
jclass jstuClass = env->GetObjectClass(stu); //獲取 Student 類對(duì)象

(4)獲取父類或者說(shuō)超類
如果 class 代表類 class 而非類 object弯屈,則該函數(shù)返回由 class 所指定的類的超類。
如果 class 指定類 object 或代表某個(gè)接口恋拷,則該函數(shù)返回 NULL资厉。
jclass GetSuperclass (JNIEnv* env,
jclass clazz);
參數(shù):
env:JNI 接口指針。
obj:Java 類對(duì)象蔬顾。
返回值:由 clazz 所代表的類的超類或 NULL宴偿。

(5)判斷 clazz1 對(duì)象是否能安全地強(qiáng)制的轉(zhuǎn)換為 clazz2
jboolean IsAssignableFrom ( JNIEnv* env,
jclass clazz1,jclass clazz2);
參數(shù):
env:JNI 接口指針。
clazz1:第一個(gè)類參數(shù)诀豁。
class2:第二個(gè)類參數(shù)窄刘。
返回值:
下列某個(gè)情況為真時(shí)返回 JNI_TRUE:
1.第一及第二個(gè)類參數(shù)引用同一個(gè) Java 類。
2.第一個(gè)類是第二個(gè)類的子類舷胜。
3.第二個(gè)類是第一個(gè)類的某個(gè)接口娩践。

2.異常操作
(1) 拋出 java.lang.Throwable 對(duì)象
jint Throw( JNIEnv* env,
jthrowable obj);
參數(shù):
env:JNI 接口指針。
obj:Java.lang.Throwable 對(duì)象。
返回值:成功時(shí)返回 0翻伺,失敗時(shí)返回負(fù)數(shù)材泄。
拋出:java.lang.Throwable 對(duì)象 obj。

(2)利用指定類的消息(由 message 指定)構(gòu)造異常對(duì)象并拋出該異常吨岭。
jint ThrowNew ( JNIEnv* env,
jclass clazz,
const char* message);
參數(shù):
env:JNI 接口指針拉宗。
clazz:java.lang.Throwable 的子類。
message:用于構(gòu)造 java.lang.Throwable 對(duì)象的消息辣辫。
返回值:成功時(shí)返回 0旦事,失敗時(shí)返回負(fù)數(shù)。
拋出:新構(gòu)造的 java.lang.Throwable 對(duì)象急灭。

(3)判斷是否是某個(gè)異常正被拋出
在平臺(tái)相關(guān)代碼調(diào)用 ExceptionClear() 或 Java 代碼處理該異常前姐浮,異常將始終保
持拋出狀態(tài)。
jthrowable ExceptionOccurred (JNIEnv* env);
參數(shù):JNI 接口指針葬馋。
返回值:返回正被拋出的異常對(duì)象单料,如果當(dāng)前無(wú)異常被拋出,則返回 NULL点楼。

(4)將異常及堆棧的回溯輸出到系統(tǒng)錯(cuò)誤報(bào)告信道
例如 stderr,該例程可便利調(diào)試操作扫尖。
void ExceptionDescribe (JNIEnv* env);
參數(shù):
env:JNI 接口指針。
返回值:無(wú)

(5)清除當(dāng)前拋出的任何異常
如果當(dāng)前無(wú)異常掠廓,則此例程不產(chǎn)生任何效果换怖。
void ExceptionClear (JNIEnv* env);
參數(shù):
env:JNI 接口指針。
返回值:無(wú)

(6)拋出致命錯(cuò)誤并且不希望虛擬機(jī)進(jìn)行修復(fù)蟀瞧。
void FatalError ( JNIEnv* env,
const char* msg);
參數(shù):
env:JNI 接口指針沉颂。
msg:錯(cuò)誤消息。
返回值:無(wú)

3.全局及局部引用
(1)創(chuàng)建 obj 參數(shù)所引用對(duì)象的新全局引用悦污。
obj 參數(shù)既可以是全局引用铸屉,也可以是局部引用。全局引用通過(guò)調(diào)用
DeleteGlobalRef()來(lái)顯式撤消切端。
jobject NewGlobalRef (JNIEnv* env,
jobject obj);
參數(shù):
env:JNI 接口指針彻坛。
obj:全局或局部引用
返回值: 返回全局引用。如果系統(tǒng)內(nèi)存不足則返回 NULL踏枣。

(2)刪除 globalRef 所指向的全局引用
void DeleteGlobalRef (JNIEnv* env,
jobject globalRef);
參數(shù):
env:JNI 接口指針昌屉。
globalRef:全局引用。
返回值:無(wú)

(3)刪除 localRef 所指向的局部引用
void DeleteLocalRef (JNIEnv* env,
jobject localRef);
參數(shù):
env:JNI 接口指針茵瀑。
localRef:局部引用间驮。
返回值:無(wú)

4.對(duì)象操作
(1)分配新 Java 對(duì)象而不調(diào)用該對(duì)象的任何構(gòu)造函數(shù)。
clazz 參數(shù)務(wù)必不要引用數(shù)組類马昨。
jobject AllocObject ( JNIEnv *env,
jclass clazz);
參數(shù):
env:JNI 接口指針竞帽。
clazz:Java 類對(duì)象扛施。
返回值: 返回 Java 對(duì)象。如果無(wú)法構(gòu)造該對(duì)象屹篓,則返回 NULL煮嫌。
拋出異常:
InstantiationException:如果該類為一個(gè)接口或抽象類。
OutOfMemoryError:如果系統(tǒng)內(nèi)存不足抱虐。

(2)構(gòu)造新 Java 對(duì)象
//參數(shù)附加在函數(shù)后面
jobject NewObject ( JNIEnv *env,
jclass clazz,
jmethodID methodID,
...);
//參數(shù)以指針形式附加
jobject NewObjectA (JNIEnv env,
jclass clazz,
jmethodID methodID,
jvalue
args);
//參數(shù)以"鏈表"形式附加
jobject NewObjectV (JNIEnv *env,
jclass clazz,
jmethodID methodID,
va_list args);

參數(shù):
env:JNI 接口指針。
clazz:Java 類對(duì)象饥脑。
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 對(duì)象笋颤,如果無(wú)法構(gòu)造該對(duì)象乳附,則返回 NULL。
拋出異常:
InstantiationException:如果該類為接口或抽象類伴澄。
OutOfMemoryError:如果系統(tǒng)內(nèi)存不足赋除。
構(gòu)造函數(shù)拋出的任何異常。

注意:該 ID 特指該類 clazz 的構(gòu)造函數(shù) ID非凌,必須通過(guò)調(diào)用 GetMethodID()獲得举农,且調(diào)
用時(shí)的方法名必須為 <init>,而返回類型必須為 void (V)敞嗡。clazz 參數(shù)務(wù)必不要引
用數(shù)組類颁糟。

(3)返回對(duì)象的類
jclass GetObjectClass ( JNIEnv *env,
jobject obj);
參數(shù):
env:JNI 接口指針。
obj:Java 對(duì)象(不能為 NULL)喉悴。
返回值:返回 Java 類對(duì)象棱貌。

(4)判斷對(duì)象是否為某個(gè)類的實(shí)例
jboolean IsInstanceOf ( JNIEnv* env,
jobject obj,
jclass clazz);
參數(shù):
env:JNI 接口指針。
obj:Java 對(duì)象(不能為 NULL)箕肃。
clazz:Java 類對(duì)象婚脱。
返回值:如果可將 obj 強(qiáng)制轉(zhuǎn)換為 clazz,則返回 JNI_TRUE勺像。否則返回 JNI_FALSE起惕。
NULL 對(duì)象可強(qiáng)制轉(zhuǎn)換為任何類。

(5)判斷兩個(gè)引用是否引用同一 Java 對(duì)象
jboolean IsSameObject ( JNIEnv *env,
jobject ref1,
jobject ref2);
參數(shù):
env:JNI 接口指針咏删。
ref1:Java 對(duì)象惹想。
ref2:Java 對(duì)象。
返回值:如果 ref1 和 ref2 引用同一 Java 對(duì)象或均為 NULL督函,則返回 JNI_TRUE嘀粱。否則
返回 JNI_FALSE激挪。

5.字符串操作
(1)利用 Unicode 字符數(shù)組構(gòu)造新的 java.lang.String 對(duì)象
jstring NewString (JNIEnv env,
const jchar
unicodeChars,
jsize len);
參數(shù):
env:JNI 接口指針。
unicodeChars:指向 Unicode 字符串的指針锋叨。
len:Unicode 字符串的長(zhǎng)度垄分。

返回值:Java 字符串對(duì)象。如果無(wú)法構(gòu)造該字符串娃磺,則為 NULL薄湿。
拋出:OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。
示例:

(2)返回 Java 字符串的長(zhǎng)度(Unicode 字符數(shù))
jsize GetStringLength (JNIEnv* env,
jstring string);
參數(shù):
env:JNI 接口指針偷卧。
string:Java 字符串對(duì)象豺瘤。
返回值:Java 字符串的長(zhǎng)度。

(3)返回指向字符串的 Unicode 字符數(shù)組的指針听诸。
該指針在調(diào)用 ReleaseStringchars() 前一直有效坐求。
如果 isCopy 非空,則在復(fù)制完成后將 isCopy 設(shè)為 JNI_TRUE晌梨。如果沒(méi)有復(fù)制桥嗤,則設(shè)
為 JNI_FALSE。
const jchar
GetStringChars ( JNIEnv* env,
jstring string,
jboolean* isCopy);
參數(shù):
env:JNI 接口指針仔蝌。
string:Java 字符串對(duì)象泛领。
isCopy:指向布爾值的指針。
返回值:指向 Unicode 字符串的指針敛惊,如果操作失敗师逸,則返回 NULL。

(4)通知虛擬機(jī)平臺(tái)相關(guān)代碼釋放 chars
void ReleaseStringChars(JNIEnv* env,
jstring string,
const jchar* chars);
參數(shù):
env:JNI 接口指針豆混。
string:Java 字符串對(duì)象篓像。
chars:指向 Unicode 字符串的指針。
返回值:無(wú)

(5)利用 UTF-8 字符數(shù)組構(gòu)造新 java.lang.String 對(duì)象
jstring NewStringUTF ( JNIEnv *env,
const char *bytes);
參數(shù):
env:JNI 接口指針皿伺。
bytes:指向 UTF-8 字符串的指針员辩。
返回值:Java 字符串對(duì)象。如果無(wú)法構(gòu)造該字符串鸵鸥,則為 NULL奠滑。
拋出異常:
OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。
示例:
jstring jstring1 = env->NewStringUTF("native string");

(6)以字節(jié)為單位返回字符串的 UTF-8 長(zhǎng)度妒穴。
jsize GetStringUTFLength ( JNIEnv* env,
jstring string);
參數(shù):
env:JNI 接口指針宋税。
string:Java 字符串對(duì)象。
返回值:返回字符串的 UTF-8

(7)獲取 UTF-8 編碼的 String 指針讼油,返回指向字符串的 UTF-8 字符數(shù)組的指針杰赛。
const char* GetStringUTFChars ( JNIEnv* env,
jstring string,
jboolean* isCopy);
參數(shù):
env:JNI 接口指針。
string:Java 字符串對(duì)象
isCopy:指向布爾值的指針矮台。
返回值:指向字符串的 UTF-8 字符數(shù)組的指針乏屯。如果操作失敗根时,則為 NULL帽蝶。
注意:該數(shù)組(返回的數(shù)組)在被 ReleaseStringUTFChars() 釋放前將一直有效耍休。
如果 isCopy 不等于 NULL,*isCopy 在復(fù)制完成后即被設(shè)為 JNI_TRUE觅彰。如果未復(fù)
制含友,則設(shè)為 JNI_FALSE替裆。

(8)通知虛擬機(jī)平臺(tái)相關(guān)代碼釋放 utf
utf 參數(shù)是一個(gè)指針,可利用 GetStringUTFChars()獲得窘问。
void ReleaseStringUTFChars (JNIEnv* env,
jstring string,
const char* utf);
參數(shù):
env:JNI 接口指針辆童。
string:Java 字符串對(duì)象
utf:指向 UTF-8 字符串的指針。
功能:通知虛擬機(jī)平臺(tái)相關(guān)代碼無(wú)需再訪問(wèn) utf南缓。

6.數(shù)組操作
(1)返回?cái)?shù)組中的元素?cái)?shù)
jsize GetArrayLength (JNIEnv *env,
jarray array);
參數(shù):
env:JNI 接口指針。
array:Java 數(shù)組對(duì)象荧呐。
返回值:數(shù)組的長(zhǎng)度汉形。

(2)構(gòu)造新的數(shù)組
它將保存類 elementClass 中的對(duì)象。所有元素初始值均設(shè)為 initialElement倍阐。
jarray NewObjectArray (JNIEnv *env,
jsize length,
class elementClass,
jobject initialElement);
參數(shù):
env:JNI 接口指針概疆。
length:數(shù)組大小。
elementClass:數(shù)組元素類峰搪。
initialElement:初始值(可為 NULL)
返回值:Java 數(shù)組對(duì)象岔冀。如果無(wú)法構(gòu)造數(shù)組,則為 NULL概耻。
拋出異常:
OutOfMemoryError:如果系統(tǒng)內(nèi)存不足使套。
注意:使用該函數(shù)時(shí),為了便于易操作性鞠柄,我們一般可以用 jobjectArray 數(shù)組類型或
得返回值侦高,例如:
jobjectArray objArray = env->NewObjectArray( );
//操作該對(duì)象,獲得該 object 數(shù)組在索引 0 處的值 ,(可以強(qiáng)制轉(zhuǎn)換類型).
env->GetObjectArrayElement(objArray, 0);

(3)返回 Object 數(shù)組的元素
jobject GetObjectArrayElement (JNIEnv *env,
jobjectArray array,
jsize index);
參數(shù):
env:JNI 接口指針厌杜。
array:Java 數(shù)組奉呛。
index:數(shù)組下標(biāo)。
返回值:Java 對(duì)象夯尽。
拋出異常:ArrayIndexOutOfBoundsException:如果 index 不是數(shù)組中的有效下標(biāo)瞧壮。

(4)設(shè)置 Object 數(shù)組的元素
void SetObjectArrayElement ( JNIEnv *env,
jobjectArray array,
jsize index,
jobject value);
參數(shù):
env:JNI 接口指針。
array:Java 數(shù)組匙握。
index:數(shù)組下標(biāo)咆槽。
value:新的值。
返回值:無(wú)

拋出異常:
ArrayIndexOutOfBoundsException:如果 index 不是數(shù)組中的有效下標(biāo)圈纺。
ArrayStoreException:如果 value 的類不是數(shù)組元素類的子類罗晕。
(5)New<PrimitiveType>Array 方法類型
用于構(gòu)造新基本類型數(shù)組對(duì)象的一系列操作济欢。下表說(shuō)明了特定的基本類型數(shù)組構(gòu)造函數(shù)。
用戶應(yīng)把 New<PrimitiveType>Array 替換為某個(gè)實(shí)際的基本類型數(shù)組構(gòu)造函數(shù)名稱小渊,然后
將 ArrayType 替換為該名稱相應(yīng)的數(shù)組類型法褥。

NativeType New<PrimitiveType>Array (JNIEnv* env,
ArrayType array,
jboolean* isCopy);
參數(shù):
env:JNI 接口指針。
length:數(shù)組長(zhǎng)度酬屉。
返回值:Java 數(shù)組半等。如果無(wú)法構(gòu)造該數(shù)組,則為 NULL呐萨。

方法族如下:
New<PrimitiveType>Array 方法族 數(shù)組類型
NewBooleanArray() jbooleanArray
NewByteArray() jbyteArray
NewCharArray() jcharArray
NewShortArray() jshortArray
NewIntArray() jintArray
NewLongArray() jlongArray
NewFloatArray() jfloatArray
NewDoubleArray() jdoubleArray

(6)Get<PrimitiveType>ArrayElements 方法類型
一組返回基本類型數(shù)組體的函數(shù)杀饵。結(jié)果在調(diào)用相應(yīng)的
Release<PrimitiveType>ArrayElements()函數(shù)前將一直有效。
由于返回的數(shù)組可能是 Java 數(shù)組的副本谬擦,因此對(duì)返回?cái)?shù)組的更改不必在基本類型
數(shù)組中反映出來(lái)切距,直到調(diào)用了 Release<PrimitiveType>ArrayElements()。如果 isCopy
不是 NULL惨远,*isCopy 在復(fù)制完成后即被設(shè)為 JNI_TRUE谜悟。如果未復(fù)制,則設(shè)為 JNI_FALSE北秽。
使用說(shuō)明:
1.將 Get<PrimitiveType>ArrayElements 替換為表中某個(gè)實(shí)際的基本類型元素訪問(wèn)
器例程名葡幸。
2.將 ArrayType 替換為對(duì)應(yīng)的數(shù)組類型。
3.將 NativeType 替換為該例程對(duì)應(yīng)的本地類型贺氓。

NativeType* Get<PrimitiveType>ArrayElements(JNIEnv* env,
ArrayType array,
jboolean* isCopy);
參數(shù):
env:JNI 接口指針蔚叨。

array:Java 字符串對(duì)象。
isCopy:指向布爾值的指針辙培。
返回值:返回指向數(shù)組元素的指針蔑水,如果操作失敗,則為 NULL扬蕊。
不管布爾數(shù)組在 Java 虛擬機(jī)中如何表示肤粱,GetBooleanArrayElements()將始終返回一
個(gè) jbooleans 類型的指針,其中每一字節(jié)代表一個(gè)元素(開包表示)厨相。內(nèi)存中將確保所有
其它類型领曼。

方法族如下:

Get<PrimitiveType>ArrayElements 方法族 數(shù)組類型 本地類型
etBooleanArrayElements() jbooleanArray jboolean
GetByteArrayElements() jbyteArray jbyte
GetCharArrayElements() jcharArray jchar
GetShortArrayElements() jshortArray jshort
GetIntArrayElements() jintArray jint
GetLongArrayElements() jlongArray jlong
GetFloatArrayElements() jfloatArray jfloat
GetDoubleArrayElements() jdoubleArray jdouble

(7)Release<PrimitiveType>ArrayElements 方法類型
通知虛擬機(jī)平臺(tái)相關(guān)代碼無(wú)需再訪問(wèn) elems 的一組函數(shù)。elems 參數(shù)是一個(gè)通過(guò)使用
對(duì)應(yīng)的 Get<PrimitiveType>ArrayElements()函數(shù)由 array 導(dǎo)出的指針蛮穿。必要時(shí)庶骄,該函數(shù)
將把對(duì) elems 的修改復(fù)制回基本類型數(shù)組。mode 參數(shù)將提供有關(guān)如何釋放數(shù)組緩沖區(qū)的
信息践磅。如果 elems 不是 array 中數(shù)組元素的副本单刁,mode 將無(wú)效。否則,mode 將具有下表
所述的功能:

模式 動(dòng)作
0 復(fù)制回內(nèi)容并釋放 elems 緩沖區(qū)
JNI_COMMIT 復(fù)制回內(nèi)容但不釋放 elems 緩沖區(qū)
JNI_ABORT 釋放緩沖區(qū)但不復(fù)制回變化

多數(shù)情況下羔飞,編程人員將把“0”傳給 mode 參數(shù)以確保固定的數(shù)組和復(fù)制的數(shù)組保
持一致肺樟。其它選項(xiàng)可以使編程人員進(jìn)一步控制內(nèi)存管理,但使用時(shí)務(wù)必慎重逻淌。
使用說(shuō)明:
1.將 ArrayType 替換為對(duì)應(yīng)的數(shù)組類型么伯。
2.將 NativeType 替換為該例程對(duì)應(yīng)的本地類型。

方法族如下:

Release<PrimitiveType>ArrayElements 方法族 數(shù)組類型 本地類型
ReleaseBooleanArrayElements() jbooleanArray jboolean
ReleaseByteArrayElements() jbyteArray jbyte
ReleaseCharArrayElements() jcharArray jchar
ReleaseShortArrayElements() jshortArray jshort
ReleaseIntArrayElements() jintArray jint
ReleaseLongArrayElements() jlongArray jlong
ReleaseFloatArrayElements() jfloatArray jfloat
ReleaseDoubleArrayElements() jdoubleArray jdouble

(8)Get<PrimitiveType>ArrayRegion 方法類型
將基本類型數(shù)組某一區(qū)域復(fù)制到緩沖區(qū)中的一組函數(shù)卡儒。
使用說(shuō)明:
1.將 Get<PrimitiveType>ArrayRegion 替換為下表的某個(gè)實(shí)際基本類型元素訪問(wèn)器例
程名田柔。
2.將 ArrayType 替換為對(duì)應(yīng)的數(shù)組類型。
3.將 NativeType 替換為該例程對(duì)應(yīng)的本地類型骨望。

void Get<PrimitiveType>ArrayRegion ( JNIEnv *env,
ArrayType array,
jsize start, jsize len,
NativeType *buf);
參數(shù);
env:
array:Java 指針硬爆。
start:起始下標(biāo)。
len:要復(fù)制的元素?cái)?shù)擎鸠。
buf:的緩沖區(qū)缀磕。
返回值:無(wú)
拋出異常:ArrayIndexOutOfBoundsException:如果區(qū)域中的某個(gè)下標(biāo)無(wú)效。

方法族如下:
Get<PrimitiveType>ArrayRegion 方法組 數(shù)組類型 本地類型
GetBooleanArrayRegion() jbooleanArray jboolean
GetByteArrayRegion() jbyteArray jbyte
GetCharArrayRegion() jcharArray jchar
GetShortArrayRegion() jshortArray jhort
GetIntArrayRegion() jintArray jint
GetLongArrayRegion() jlongArray jlong
GetFloatArrayRegion() jfloatArray jloat
GetDoubleArrayRegion() jdoubleArray jdouble

(8)Set<PrimitiveType>ArrayRegion 方法類型
將基本類型數(shù)組的某一區(qū)域從緩沖區(qū)中復(fù)制回來(lái)的一組函數(shù)劣光。
使用說(shuō)明:
1.將 Set<PrimitiveType>ArrayRegion 替換為表中的實(shí)際基本類型元素訪問(wèn)器例程名袜蚕。
2.將 ArrayType 替換為對(duì)應(yīng)的數(shù)組類型。
3.將 NativeType 替換為該例程對(duì)應(yīng)的本地類型赎线。
void Set<PrimitiveType>ArrayRegion ( JNIEnv *env,
ArrayType array,
jsize start,jsize len,
NativeType *buf);
參數(shù);

env:JNI 接口指針廷没。
array:ava 數(shù)組糊饱。
start:起始下標(biāo)垂寥。
len:要復(fù)制的元素?cái)?shù)個(gè)數(shù)
buf:源緩沖區(qū)。
返回值:無(wú)
拋出異常:
ArrayIndexOutOfBoundsException:如果區(qū)域中的某個(gè)下標(biāo)無(wú)效另锋。

方法族如下:
Set<PrimitiveType>ArrayRegion 方法族 數(shù)組類型 本地類型
SetBooleanArrayRegion() booleanArray jboolean
SetByteArrayRegion() jbyteArray jbyte
SetCharArrayRegion() jcharArray jchar
SetShortArrayRegion() jshortArray jshortF
SetIntArrayRegion() jintArray jint
SetLongArrayRegion() jlongArray jlong
SetFloatArrayRegion() jfloatArray jfloat
SetDoubleArrayRegion() jdoubleArray jdouble

7.訪問(wèn)對(duì)象的屬性和方法
7.1 實(shí)例屬性的訪問(wèn)
(1)回類的實(shí)例(非靜態(tài))域的屬性 ID
該域由其名稱及簽名指定滞项。訪問(wèn)器函數(shù)的 Get<type>Field 及 Set<type>Field 系列使用
域 ID 檢索對(duì)象域。
GetFieldID() 不能用于獲取數(shù)組的長(zhǎng)度域夭坪。應(yīng)使用 GetArrayLength()文判。
jfieldID GetFieldID (JNIEnv *env,
jclass clazz,
const char *name,
const char *sig);
參數(shù):
env:JNI 接口指針。
clazz:Java 類對(duì)象
name:該屬性的 Name 名稱
sig:該屬性的域簽名
返回值:屬性 ID室梅。如果操作失敗戏仓,則返回 NULL。
拋出異常:
NoSuchFieldError:如果找不到指定的域亡鼠。
ExceptionInInitializerError:如果由于異常而導(dǎo)致類初始化程序失敗赏殃。
OutOfMemoryError:如果系統(tǒng)內(nèi)存不足。
示例:

Java 層:所在類 com.hello.hellojni3.Student
String name;
Native 層:
extern "C"
JNIEXPORT jstring JNICALL
Java_com_hello_hellojni3_MainActivity_setNameFromNative(JNIEnv* env,
jobject instance,
jobject stu) { //Student 對(duì)象
// TODO
// 1. 獲取類型
jclass jstuClass = env->FindClass("com/hello/hellojni3/Student");
// 2. 獲取域 ID
jfieldID jfieldID1 =
env->GetFieldID(jstuClass, "name", "Ljava/lang/StrinGetFieldID
jstring jstring1 = env->NewStringUTF("native string");
env->SetObjectField(stu, jfieldID1, jstring1);
return jstring1;
}

(2)Get<type>Field 方法類型
該訪問(wèn)器例程系列返回對(duì)象的實(shí)例(非靜態(tài))域的值间涵。要訪問(wèn)的域由通過(guò)調(diào)用 GetFieldID()
而得到的域 ID 指定仁热。
NativeType Get<type>Field (JNIEnv* env,
jobject obj,
jfieldID fieldID);
參數(shù):
env:JNI 接口指針。
obj:ava 對(duì)象(不能為 NULL)
fieldID:有效的域 ID
返回值:屬性的內(nèi)容勾哩。

方法族如下:
Get<type>Field 本地類型
GetObjectField() jobject
GetBooleanField() jboolean
GetByteField() jbyte
GetCharField() jchar
GetShortField() jshort
GetIntField() jint
GetLongField() jlong
GetFloatField() jfloat
GetDoubleField() jdouble

(3)Set<type>Field 方法類型
該訪問(wèn)器例程系列設(shè)置對(duì)象的實(shí)例(非靜態(tài))屬性的值抗蠢。要訪問(wèn)的屬性由通過(guò)調(diào)用
SetFieldID() 而得到的屬性 ID 指定举哟。
void Set<type>Field (JNIEnv *env,
jobject obj,
jfieldID fieldID,
NativeType value);
參數(shù):
env:JNI 接口指針。
obj:Java 對(duì)象(不能為 NULL)迅矛。
fieldID:有效的域 ID妨猩。
value:新的值。
返回值:無(wú)

方法族如下:
Set<type>Field 方法族 本地類型
SetObjectField() jobject
SetBooleanField() jboolean
SetByteField() jbyte
SetCharField() jchar
SetShortField() jshort
SetIntField() jint
SetFloatField() jfloat
SetDoubleField() jdouble

7.2 靜態(tài)屬性的訪問(wèn)
jfieldID GetStaticFieldID ( JNIEnv *env,
jclass clazz,
const char *name,
const char sig);
NativeType GetStatic<type>Field ( JNIEnv
env,
jclass clazz,
jfieldID fieldID);
void SetStatic<type>Field ( JNIEnv *env,
jclass clazz,
jfieldID fieldID,
NativeType value);
參數(shù):
env:JNI 接口指針诬乞。
clazz:Java 類對(duì)象
name:方法名
sig:方法的簽名
fieldID:方法 ID册赛,如果找不到指定的方法,則為 NULL震嫉。
value:新的值
它們與實(shí)例屬性的唯一區(qū)別在于第二個(gè)參數(shù) jclass clazz 代表的是類引用森瘪,而不是類
實(shí)例。

7.3 調(diào)用實(shí)例方法
(1)返回類或接口實(shí)例(非靜態(tài))方法的方法 ID
方法可在某個(gè) class 的超類中定義,也可從 class 繼承票堵。該方法由其名稱和簽名決定扼睬。
GetMethodID() 可使未初始化的類初始化。要獲得構(gòu)造函數(shù)的方法 ID悴势,應(yīng)將<init>作為方
法名窗宇,同時(shí)將 void (V) 作為返回類型。
jmethodID GetMethodID(JNIEnv *env,
jclass class,
const char *name,
const char *sig);
參數(shù):
env:JNI 接口指針特纤。
class:Java 類對(duì)象
name:方法名
sig:方法的簽名
返回值:方法 ID军俊,如果找不到指定的方法,則為 NULL捧存。
拋出異常:
NoSuchMethodError:如果找不到指定方法粪躬。
ExceptionInInitializerError:如果由于異常而導(dǎo)致類初始化程序失敗。
OutOfMemoryError:如果系統(tǒng)內(nèi)存不足昔穴。

示例:
java 層:方法所在類為 com/hello/hellojni3/Student
public int getId() {return id;}
Native 層:
extern "C"
JNIEXPORT jstring JNICALL
Java_com_hello_hellojni3_MainActivity_CallgetNameFromNative(
JNIEnv *env, jobject instance, jobject stu) {
// 1. 獲取類型(參見 FindClass 方法)
jclass jstuClass =
env->FindClass("com/hello/hellojni3/Student");
// jclass clazz:類型
// const char *name:名稱
// const char *sig:簽名
// 2. 獲取方法 ID
jmethodID jmethodID1 = env->GetMethodID(jstuClass, "getId", "()I");
// 3. 調(diào)用方法
jint jint1 = env->CallIntMethod(stu, jmethodID1);
return jstring1;

(2)Call<type>Method镰官,Call<type>MethodA,Call<type>MethodV 方法類型
//參數(shù)附加在函數(shù)后面
NativeType Call<type>Method (JNIEnv* env,
jobject obj,
jmethodID methodID,
...);
//參數(shù)以指針形式附加
NativeType Call<type>MethodA (JNIEnv *env,
jobject obj,
jmethodID methodID,
jvalue *args);
//參數(shù)以"鏈表"形式附加
NativeType Call<type>MethodV (JNIEnv *env,
jobject obj,
jmethodID methodID,
va_list args);
參數(shù):
env:
obj:Java 對(duì)象
methodID:方法 ID
args:傳給構(gòu)造函數(shù)的參數(shù)數(shù)組吗货。
返回值:返回調(diào)用 Java 方法的結(jié)果泳唠。
拋出異常:執(zhí)行 Java 方法時(shí)拋出的異常。

下表根據(jù)結(jié)果類型說(shuō)明了各個(gè)方法類型宙搬。用戶應(yīng)將 Call<type>Method 中的 type 替換
為所調(diào)用方法的 Java 類型(或使用表中的實(shí)際方法名)笨腥,同時(shí)將 NativeType 替換為該方法
相應(yīng)的本地類型。省略掉了其他兩種類型勇垛。
Java 層返回值 方法族 本地返回類型 NativeType
返回值為 void CallVoidMethod()A / V (無(wú))
回值為引用類型 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

7.4 調(diào)用靜態(tài)方法(也存在如下方法群)
jfieldID GetStaticMethodID (JNIEnv *env,
jclass class,
20 / 21
20 / 21
const char *name,
const char sig);
NativeType Call<type>Method (JNIEnv
env,
jclass class,
jfieldID fieldID);
參數(shù):
env:JNI 接口指針脖母。
class:Java 類對(duì)象。
name:該屬性的 Name 名稱窥摄。
sig:該屬性的域簽名镶奉。
fieldID:有效的域 ID
它們與于實(shí)例方法的唯一區(qū)別在于第二個(gè)參數(shù) jclass class 代表的是類引用,而不是
類實(shí)例。

8.注冊(cè)本地方法
(1)向 class 參數(shù)指定的類注冊(cè)本地方法
methods 參數(shù)將指定 JNINativeMethod 結(jié)構(gòu)的數(shù)組哨苛,其中包含本地方法的名稱鸽凶、簽名和
函數(shù)指針。nMethods 參數(shù)將指定數(shù)組中的本地方法數(shù)建峭。
jint RegisterNatives (JNIEnv *env,
jclass class,
const JNINativeMethod *methods,
jint nMethods);
參數(shù):
env:JNI 接口指針玻侥。
class:Java 類對(duì)象。
methods:類中本地方法和具體實(shí)現(xiàn)方法的映射指針亿蒸。
nMethods:類中的本地方法數(shù)凑兰。
返回值:成功時(shí)返回 "0";失敗時(shí)返回負(fù)數(shù)边锁。
拋出異常:
NoSuchMethodError:如果找不到指定的方法或方法不是本地方法姑食。

JNINativeMethod 結(jié)構(gòu)定義如下所示:
typedef struct {
char *name; //方法名
char *signature; //方法簽名
void *fnPtr; //方法指針(Native 中所對(duì)應(yīng)的方法)
} JNINativeMethod;

示例:
JNINativeMethod jniNativeMethod = {
"stringFromJNI1", //方法名
"(I)Ljava/lang/String;", //方法簽名
(void*)stringFromJNI1 //指向方法所在的地址
};

extern "C"
jstring JNICALL stringFromJNI1(
JNIEnv env, jobject instance, jint n) {
// TODO
if(n < 2){
return env->NewStringUTF("C++");
} else {
return env->NewStringUTF("C#");
}
}
extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad(
JavaVM
vm, // java 虛擬機(jī)指針
void* reserved // 保留
){
// 獲取當(dāng)前環(huán)境指針
JNIEnv* env = NULL;
jint ret = vm->GetEnv((void*)&env, JNI_VERSION_1_6);
if(ret != JNI_OK){
return 0;
}
// 動(dòng)態(tài)的注冊(cè) jni 函數(shù)
// 需要先獲取環(huán)境指針
// 獲取類類型
const char
className = "com/bluelesson/hellojni3/MainActivity";
jclass clazz = env->FindClass(className);
env->RegisterNatives(clazz,&jniNativeMethod,1);
// 返回 版本
return JNI_VERSION_1_6;
}

函數(shù)指針通常必須有下列簽名:
ReturnType (*fnPtr)(JNIEnv *env, jobject objectOrClass, ...);

(2)取消注冊(cè)類的本地方法
類將返回到鏈接或注冊(cè)了本地方法函數(shù)前的狀態(tài)。該函數(shù)不應(yīng)在常規(guī)平臺(tái)相關(guān)代碼中使
用茅坛。相反音半,它可以為某些程序提供一種重新加載和重新鏈接本地庫(kù)的途徑。
jint UnregisterNatives(JNIEnv *env, jclass class);
參數(shù):
env:JNI 接口指針贡蓖。
class:Java 類對(duì)象曹鸠。
返回值:成功時(shí)返回“0”;失敗時(shí)返回負(fù)數(shù)斥铺。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末彻桃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子晾蜘,更是在濱河造成了極大的恐慌邻眷,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笙纤,死亡現(xiàn)場(chǎng)離奇詭異耗溜,居然都是意外死亡组力,警方通過(guò)查閱死者的電腦和手機(jī)省容,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)燎字,“玉大人腥椒,你說(shuō)我怎么就攤上這事『蜓埽” “怎么了笼蛛?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蛉鹿。 經(jīng)常有香客問(wèn)我滨砍,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任惋戏,我火速辦了婚禮领追,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘响逢。我一直安慰自己绒窑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布舔亭。 她就那樣靜靜地躺著些膨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钦铺。 梳的紋絲不亂的頭發(fā)上订雾,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音矛洞,去河邊找鬼葬燎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缚甩,可吹牛的內(nèi)容都是我干的谱净。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼擅威,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼壕探!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起郊丛,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤李请,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后厉熟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體导盅,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年揍瑟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了白翻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绢片,死狀恐怖滤馍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情底循,我是刑警寧澤巢株,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站熙涤,受9級(jí)特大地震影響阁苞,放射性物質(zhì)發(fā)生泄漏困檩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一那槽、第九天 我趴在偏房一處隱蔽的房頂上張望窗看。 院中可真熱鬧,春花似錦倦炒、人聲如沸显沈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拉讯。三九已至,卻和暖如春鳖藕,著一層夾襖步出監(jiān)牢的瞬間魔慷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工著恩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留院尔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓喉誊,卻偏偏與公主長(zhǎng)得像邀摆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子伍茄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容