概述
對(duì)于JNI冻璃,有些童鞋在沒(méi)有接觸過(guò)的時(shí)候,可能會(huì)覺(jué)得比較復(fù)雜债查,但是其實(shí)當(dāng)你真正去了解、去使用的時(shí)候瓜挽,就會(huì)發(fā)現(xiàn)JNI的使用還是比較簡(jiǎn)單的盹廷,JNI本身提供了一系列的API讓我們可以在native方法中操作java。JNI的使用無(wú)非也就是使用這些接口和java交互久橙。這幾天在學(xué)習(xí)JNI接口的時(shí)候俄占,發(fā)現(xiàn)網(wǎng)上搜索的JNI的中文雖然不少,但是很多都是零零碎碎的小例子剥汤,有一些官方文檔的翻譯颠放,但要么是不全面,要么是資料比較舊了吭敢,干脆自己根據(jù)java native interface specification整理了一份技術(shù)資料碰凶。當(dāng)然,很多時(shí)候看中文資料是詞不達(dá)意的鹿驼,如果文中有疑問(wèn)的地方歡迎指出欲低,或者翻閱原文
首先,JNI是一個(gè)本地編程接口畜晰。它允許運(yùn)行在Java虛擬機(jī)的Java代碼與用其他語(yǔ)言(如C,C++和匯編)編寫的庫(kù)交互
JNI最大的好處是JNI不受Java虛擬機(jī)實(shí)現(xiàn)方式的限制砾莱,因此,Java虛擬機(jī)廠商添加JNI的支持并不會(huì)影響虛擬機(jī)其它功能模塊凄鼻。native代碼只需要編寫一遍腊瑟,就可以在所有支持JNI的虛擬機(jī)上工作聚假。
通過(guò)JNI,你可以在native代碼中:
- 創(chuàng)建闰非、檢查或者更新java對(duì)象
- 調(diào)用java方法
- 捕捉和拋出異常
- 加載class和獲取class信息
- 運(yùn)行時(shí)類型檢查
JNI接口函數(shù)和指針
本地代碼通過(guò)JNI函數(shù)(接口指針膘格,接口指針是指針的指針)來(lái)訪問(wèn)java VM。
JNI接口指針只在當(dāng)前線程有效财松,因此在native方法中不要跨線程傳遞接口指針參數(shù)瘪贱。native方法接收J(rèn)NI接口指針參數(shù),VM確保在同一個(gè)線程中調(diào)用native方法的時(shí)候辆毡,傳遞同一個(gè)接口指針給接口指針給native方法菜秦。然而,native方法可能在Java中的不同線程中調(diào)用舶掖,所以native方法接收到的接口指針可能是不一樣的球昨。
編譯、加載和鏈接本地方法
編譯
Java VM是多線程的 眨攘,所以native libraries應(yīng)該用多線程編譯器來(lái)進(jìn)行編譯和鏈接褪尝。例如使用Sun Studio compiler編譯器的時(shí)候,要為c++代碼添加-mt
標(biāo)記期犬;使用 GNU gcc compiler的時(shí)候,需添加-D_REENTRANT
或-D_POSIX_C_SOURCE
加載
native庫(kù)通過(guò)System.loadLibrary
方法進(jìn)行加載避诽。如:
package pkg;
class Cls {
native double f(int i, String s);
static {
System.loadLibrary("pkg_Cls");
}
}
系統(tǒng)會(huì)對(duì)library名會(huì)進(jìn)行轉(zhuǎn)換龟虎,在不同平臺(tái)上有不同的轉(zhuǎn)換方式,例如沙庐,Solaris系統(tǒng)轉(zhuǎn)換pkg_Cls為libpkg_Cls.so鲤妥,而Win32系統(tǒng)轉(zhuǎn)換pkg_Cls為pkg_Cls.dll
鏈接
如果系統(tǒng)不支持動(dòng)態(tài)鏈接,那么所有本地方法需要預(yù)鏈接到虛擬機(jī)拱雏,這種情況下棉安,VM已經(jīng)完成System.loadLibrary
了。程序員也可以調(diào)用JNI函數(shù)RegisterNatives()來(lái)注冊(cè)該類關(guān)聯(lián)的本地方法
Native Method命名解析
一個(gè)本地方法名有以下幾個(gè)組成部分:
- 前綴
Java_
- 完整類名(類名中的
.
用_
代替) - 下劃線
_
- 方法名(方法名中的特殊字符需要轉(zhuǎn)義)
- 參數(shù)簽名(非必須铸抑,有重載方法的時(shí)候才需要)贡耽,如果有重載的本地方法,需要再添加兩個(gè)下劃線
__
鹊汛,然后再添加方法簽名(由java字段描述符描述蒲赂,用_
代替描述符中的包名分割/
符,簽名中的特殊字符需要轉(zhuǎn)義)
Unicode 轉(zhuǎn)義字符
轉(zhuǎn)義符 | 說(shuō)明 |
---|---|
_0XXXX | 一個(gè)Unicode字符XXXX刁憋。注意小寫是用來(lái)表示非ascii Unicode字符, 如:_0abcd與_0ABCD不相同 |
_1 | 字符_
|
_2 | 參數(shù)簽名中的字符;
|
_3 | 參數(shù)簽名中的字符[
|
<span id="java_signatures"></span>
java字段描述符
Java 類型 | 符號(hào) |
---|---|
Boolean | Z |
Byte | B |
Char | C |
Short | S |
Int | I |
Long | J |
Float | F |
Double | D |
Void | V |
數(shù)組 | [ , 如:int[] -> [I , int[][] -> [[I , Thread[] -> [Ljava/lang/Thread;
|
objects | 以"L"開(kāi)頭滥嘴,以";"結(jié)尾,中間是用"/" 隔開(kāi)的包及類名至耻。比如:Ljava/lang/String; 如果是嵌套類若皱,則用$ 來(lái)表示嵌套镊叁。例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z " |
舉例
package pkg;
class Cls {
//對(duì)應(yīng)本地方法名:Java_pkg_Cls_f__ILjava_lang_String_2
native double f(int i, String s);
...
}
Native方法參數(shù)
- JNI接口指針是native方法的第一個(gè)參數(shù),JNI接口指針的類型是
JNIEnv
走触。 - 第二個(gè)參數(shù)取決于native method是否靜態(tài)方法晦譬,如果是非靜態(tài)方法,那么第二個(gè)參數(shù)是對(duì)對(duì)象的引用饺汹,如果是靜態(tài)方法蛔添,則第二個(gè)參數(shù)是對(duì)它的class類的引用
- 剩下的參數(shù)跟Java方法參數(shù)一一對(duì)應(yīng)
package pkg;
class Cls {
native double f(int i, String s);
...
}
//注意,c和c++在使用JNI接口的時(shí)候有點(diǎn)不一致兜辞,請(qǐng)仔細(xì)觀察通過(guò)env調(diào)用接口的調(diào)用方式
//C版本
jdouble Java_pkg_Cls_f__ILjava_lang_String_2 (
JNIEnv *env, /* interface pointer */
jobject obj, /* "this" pointer */
jint i, /* argument #1 */
jstring s) /* argument #2 */
{
/* Obtain a C-copy of the Java string */
const char *str = (*env)->GetStringUTFChars(env, s, 0);
/* process the string */
...
/* Now we are done with str */
(*env)->ReleaseStringUTFChars(env, s, str);
return ...
}
//C++版本
extern "C" /* specify the C calling convention */
jdouble Java_pkg_Cls_f__ILjava_lang_String_2 (
JNIEnv *env, /* interface pointer */
jobject obj, /* "this" pointer */
jint i, /* argument #1 */
jstring s) /* argument #2 */
{
const char *str = env->GetStringUTFChars(s, 0);
...
env->ReleaseStringUTFChars(s, str);
return ...
}
java對(duì)象引用
- 基本類型(如整型迎瞧,字符等)在Java和native之間是采用值傳遞
- Java對(duì)象采用的是引用傳遞
虛擬機(jī)必須保持已傳遞給native的對(duì)象的引用,以使這些對(duì)象不被垃圾回收器回收逸吵。native code也必須有一種方法通知虛擬機(jī)它不再需要某個(gè)對(duì)象凶硅,并且垃圾收集器必須能夠?qū)⑵浠厥?/p>
全局引用、局部引用和弱全局引用
JNI中使用的引用可以劃分為三類:全局引用
扫皱、局部引用
和弱全局引用
足绅。局部引用在方法調(diào)用的時(shí)候有效,在方法調(diào)用結(jié)束之后會(huì)自動(dòng)釋放韩脑。全局引用會(huì)一直可用氢妈,直到顯式地對(duì)其進(jìn)行釋放。弱全局引用跟全局引用的區(qū)別是弱全局引用持有的java對(duì)象可以被VM進(jìn)行回收段多,所以才使用弱全局引用前首量,我們需要對(duì)其進(jìn)行檢測(cè),看它對(duì)應(yīng)的對(duì)象是否被回收了进苍。
對(duì)象是作為局部引用傳遞給native方法的加缘,所有通過(guò)JNIEnv
方法(也就是JNI提供的API)返回的java對(duì)象都是局部引用。JNI允許程序從局部引用創(chuàng)建一個(gè)全局引用觉啊。JNIEnv
的方法既可以接收全局引用也可以接收局部引用拣宏。一個(gè)native方法既可以返回局部引用也可以返回全局引用。
大多數(shù)情況下杠人,在方法調(diào)用結(jié)束之后勋乾,我們依賴VM去幫我們釋放所有局部引用,但是以下幾種情況下嗡善,我們應(yīng)該顯式地釋放局部引用:
- 方法中創(chuàng)建了一個(gè)比較大的java對(duì)象的市俊,并持有其局部引用,使用完之后滤奈,如果接下來(lái)都不再需要使用了摆昧,如果仍然不對(duì)它進(jìn)行釋放的話,在方法結(jié)束之前蜒程,這個(gè)對(duì)象都不會(huì)進(jìn)行釋放绅你,這樣會(huì)對(duì)資源造成浪費(fèi)
- JNI會(huì)將創(chuàng)建的局部引用都存儲(chǔ)在一個(gè)局部引用表中伺帘,如果這個(gè)表超過(guò)了最大容量限制,就會(huì)造成局部引用表溢出忌锯,使程序崩潰伪嫁。比如在一個(gè)循環(huán)中創(chuàng)建局部引用,最好在每一輪循環(huán)中釋放局部引用偶垮,否則隨著循環(huán)次數(shù)增加张咳,很可能就內(nèi)存溢出了
局部引用僅僅在其創(chuàng)建的線程內(nèi)有效,native代碼不能跨線程傳遞局部引用似舵。
訪問(wèn)字段和方法
JNI允許native代碼訪問(wèn)對(duì)象的成員以及調(diào)用它的方法脚猾,通過(guò)兩個(gè)步驟即可實(shí)現(xiàn)訪問(wèn),比如砚哗,我們需要調(diào)用cls
中的f
方法:
jmethodID mid = env->GetMethodID(cls, "f", "(ILjava/lang/String;)D");//mid可以重復(fù)使用
jdouble result = env->CallDoubleMethod(obj, mid, 10, str);
但是需要注意的是龙助,字段ID或方法ID并不能防止VM卸載該類。當(dāng)類被卸載后蛛芥,方法ID和字段ID將變成不可用的提鸟。因此,我們需要確保:
- 持有class的引用仅淑,讓它不被卸載称勋,或者
- 重新獲取方法id或者字段id
程序錯(cuò)誤檢測(cè)
JNI不對(duì)空指針或非法參數(shù)類型等錯(cuò)誤進(jìn)行檢測(cè),因?yàn)椋?/p>
- 檢查所有可能的錯(cuò)誤會(huì)降低方法執(zhí)行的性能
- 在很多時(shí)候涯竟,沒(méi)有足夠的運(yùn)行時(shí)信息去進(jìn)行檢測(cè)
程序員不得傳遞一個(gè)非法指針或者錯(cuò)誤的類型給JNI函數(shù)铣缠,否則可能會(huì)導(dǎo)致系統(tǒng)異常貨虛擬機(jī)崩潰
Java異常
JNI允許本地方法拋出處理任何異常,也可以處理Java中拋出的異常昆禽,剩下沒(méi)有處理的異常會(huì)繼續(xù)給VM處理
異常和錯(cuò)誤碼
大多數(shù)情況下,JNI提供的方法通過(guò)返回錯(cuò)誤碼或者拋出java異常來(lái)處理錯(cuò)誤蝇庭,因此醉鳖,程序中可以:
- 檢查JNI函數(shù)返回值
- 調(diào)用
ExceptionOccurred()
方法,獲取方法中拋出的異常
有兩種情況下哮内,程序需要優(yōu)先檢測(cè)java異常而不是先檢測(cè)返回碼
- 通過(guò)JNI調(diào)用Java方法的時(shí)候盗棵,需要
ExceptionOccurred()
檢測(cè)是否在Java方法中拋出了異常 - 一些訪問(wèn)數(shù)組的方法,它不返回錯(cuò)誤碼北发,但是會(huì)拋出
ArrayIndexOutOfBoundsException
或者ArrayStoreException
異常
異常處理
有兩種方法可以在本地方法中處理異常
- 檢測(cè)到異常的時(shí)候立即返回纹因,異常將會(huì)在調(diào)用該本地代碼的地方拋出
- 在本地方法中調(diào)用
ExceptionClear()
清除異常,處理接下來(lái)的邏輯
異常拋出的時(shí)琳拨,本地方法需清除異常后瞭恰,才能繼續(xù)調(diào)用其他JNI接口方法,有異常發(fā)生后狱庇,只有以下方法才能被安全調(diào)用:
ExceptionOccurred()
ExceptionDescribe()
ExceptionClear()
ExceptionCheck()
ReleaseStringChars()
ReleaseStringUTFChars()
ReleaseStringCritical()
Release<Type>ArrayElements()
ReleasePrimitiveArrayCritical()
DeleteLocalRef()
DeleteGlobalRef()
DeleteWeakGlobalRef()
MonitorExit()
PushLocalFrame()
PopLocalFrame()
原始類型
Java 類型 | native類型 | 描述 |
---|---|---|
boolean | jboolean | unsigned 8 bits |
byte | jbyte | signed 8 bits |
char | jchar | unsigned 16 bits |
short | jshort | signed 16 bits |
int | jint | signed 32 bits |
long | jlong | signed 64 bits |
float | jfloat | 32 bits |
double | jdouble | 64 bits |
void | void | N/A |
JNI中還定義了以下兩個(gè)宏定義方便使用:
#define JNI_FALSE 0
#define JNI_TRUE 1
引用類型
JNI為不同的java對(duì)象提供了不同的引用類型惊畏,JNI引用類型如下:
在c里面恶耽,所有JNI引用類型其實(shí)都是
jobject
字段和方法ID
在C中,字段和方法ID是一個(gè)指向結(jié)構(gòu)體的指針
struct _jfieldID; /* opaque structure */
typedef struct _jfieldID* jfieldID; /* field IDs */
struct _jmethodID; /* opaque structure */
typedef struct _jmethodID* jmethodID; /* method IDs */
值類型
值類型jvalue
是一個(gè)聯(lián)合體結(jié)構(gòu)颜启,定義如下:
typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;
簽名類型描述
請(qǐng)參考:java字段描述符
如:
//方法簽名為:(ILjava/lang/String;[I)J
long f (int n, String s, int[] arr);
UTF-8字符
JNI的 UTF-8與標(biāo)準(zhǔn)的 UTF-8格式有兩個(gè)區(qū)別:
- 空字符
(char)0
使用雙字節(jié)格式編碼偷俭,而不是單字節(jié)編碼,所以Java虛擬機(jī)的UTF-8字符串不可能有嵌入的空值缰盏。 - 只使用單字節(jié)涌萤、雙字節(jié)和三字節(jié)編碼格式,不支持標(biāo)準(zhǔn)的四字節(jié)編碼口猜,用
two-times-three-byte
格式代替
JNI接口函數(shù)
在下面的說(shuō)明中负溪,必須
說(shuō)明JNI函數(shù)必須接受一個(gè)非空對(duì)象,你必須保證傳入的參數(shù)不為空暮的,JNI函數(shù)不需要再對(duì)它進(jìn)行空指針判斷
返回碼說(shuō)明
#define JNI_OK (0) /* no error */
#define JNI_ERR (-1) /* generic error */
#define JNI_EDETACHED (-2) /* thread detached from the VM */
#define JNI_EVERSION (-3) /* JNI version error */
#define JNI_COMMIT 1 /* copy content, do not free buffer */
#define JNI_ABORT 2 /* free buffer w/o copying back */
接口詳細(xì)
/**
* 返回本地方法接口的版本
*
* @param env JNI接口指針
*
* @return 高16位返回主版本號(hào)笙以,低16位返回次版本號(hào),如在JDK/JRE 1.6中,返回0x00010006冻辩。也有可能返回 JNI_EDETACHED 和 JNI_EVERSION 錯(cuò)誤碼
*/
jint (*GetVersion)(JNIEnv *);
/**
* 從二進(jìn)制的.class的數(shù)據(jù)緩沖區(qū)中加載類
*
* @param env JNI接口指針
* @param name UTF8編碼的需要加載的類的名字
* @param loader 類加載器
* @param buf 包含.class字節(jié)碼的數(shù)組
* @param bufLen 長(zhǎng)度
*
* @return class對(duì)象或NULL
*
* @throws ClassFormatError 不是有效的class數(shù)據(jù)
* @throws ClassCircularityError 類或接口是自身的父類或自身繼承了該接口
* @throws OutOfMemoryError 內(nèi)存不足
* @throws SecurityException 如果該類是屬于java包的
*/
jclass (*DefineClass)(JNIEnv *, const char *, jobject, const jbyte *, jsize);
/**
* 用于加載本地定義的類
*
* @param env JNI接口指針
* @param name 完整的包名("/"代替".") 或 數(shù)組類型字段描述("["開(kāi)頭猖腕,緊跟簽名描述),如"java/lang/String" for java.lang.String, "[Ljava/lang/Object;" for java.lang.Object[]
*
* @return class對(duì)象或NULL
*
* @throws ClassFormatError 不是有效的class數(shù)據(jù)
* @throws ClassCircularityError 類或接口是自身的父類或自身繼承了該接口
* @throws OutOfMemoryError 內(nèi)存不足
* @throws NoClassDefFoundError 找不到name對(duì)應(yīng)的class類
*/
jclass (*FindClass)(JNIEnv *, const char *);
/**
* 從java.lang.reflect.Method 或 java.lang.reflect.Constructor 獲取method ID
*
* @param env JNI接口指針
* @param method java.lang.reflect.Method 或 java.lang.reflect.Constructor對(duì)象
*
* @return 方法ID
*/
jmethodID (*FromReflectedMethod)(JNIEnv *, jobject);
/**
* 從java.lang.reflect.Field獲取field ID
*
* @param env JNI接口指針
* @param field java.lang.reflect.Field對(duì)象
*
* @return field ID
*/
jfieldID (*FromReflectedField)(JNIEnv *, jobject);
/**
* 從method ID獲取 java.lang.reflect.Method 或 java.lang.reflect.Constructor 對(duì)象
*
* @param env JNI接口指針
* @param cls 該方法的類對(duì)象
* @param methodID 方法ID
* @param isStatic 是否靜態(tài)方法
*
* @return java.lang.reflect.Method 或 java.lang.reflect.Constructor 對(duì)象
*
* @throws OutOfMemoryError 內(nèi)存不足
*/
jobject (*ToReflectedMethod)(JNIEnv *, jclass, jmethodID, jboolean);
/**
* 如果clazz不是class對(duì)象或接口恨闪,則返回該class的超類
*
* @param env JNI接口指針
* @param clazz class對(duì)象
*
* @return 返回輸入類的父類 或 NULL
*/
jclass (*GetSuperclass)(JNIEnv *, jclass);
/**
* class1是否可以安全地轉(zhuǎn)換為class2倘感,以下三種情況會(huì)返回TRUE
* 1. 當(dāng)class1和class2是同一個(gè)java class的引用
* 2. class1是class2的子類
* 3. class2是class1的某個(gè)接口
*
* @param env JNI接口指針
* @param clazz1 class1
* @param clazz2 class2
*
* @return JNI_TRUE or JNI_FALSE
*/
jboolean (*IsAssignableFrom)(JNIEnv *, jclass, jclass);
/**
* 根據(jù) field ID 獲取 java.lang.reflect.Field 對(duì)象
*
* @param env JNI接口指針
* @param cls 該方法的類對(duì)象
* @param fieldID 字段ID
* @param isStatic 是否靜態(tài)變量
*
* @return java.lang.reflect.Field 對(duì)象
*
* @throws OutOfMemoryError 內(nèi)存不足
*/
jobject (*ToReflectedField)(JNIEnv *, jclass, jfieldID, jboolean);
/**
* 拋出異常
*
* @param env JNI接口指針
* @param obj java.lang.Throwable 對(duì)象
*
* @return 0:成功, 負(fù)數(shù):失敗
*
* @throws Throwable
*/
jint (*Throw)(JNIEnv *, jthrowable);
/**
* 根據(jù)clazz和message構(gòu)造一個(gè)異常對(duì)象咙咽,并將它拋出
*
* @param env JNI接口指針
* @param clazz java.lang.Throwable的子類
* @param message 錯(cuò)誤信息
*
* @return 0:成功老玛, 負(fù)數(shù):失敗
*
* @throws Throwable
*/
jint (*ThrowNew)(JNIEnv *, jclass, const char *);
/**
* 判斷是否有異常拋出,在調(diào)用ExceptionClear()或java代碼處理了exception之前钧敞,都可以用這個(gè)方法判斷是否有異常
*
* @param env JNI接口指針
*
* @return 異常對(duì)象 or NULL
*/
jthrowable (*ExceptionOccurred)(JNIEnv *);
/**
* 打印異常信息
*
* @param env JNI接口指針
*/
void (*ExceptionDescribe)(JNIEnv *);
/**
* 清除所有已拋出的異常
*
* @param env JNI接口指針
*/
void (*ExceptionClear)(JNIEnv *);
/**
* 拋出致命錯(cuò)誤并且不希望虛擬機(jī)進(jìn)行恢復(fù)蜡豹。無(wú)返回值
*
* @param env JNI接口指針
* @param msg 錯(cuò)誤信息
*/
void (*FatalError)(JNIEnv *, const char *);
/**
* 創(chuàng)建一個(gè)新的本地引用幀
*
* @param env JNI接口指針
* @param capacity 容量
*
* @return 0:成功,負(fù)數(shù):失敗
*
* @throws OutOfMemoryError
*/
jint (*PushLocalFrame)(JNIEnv *, jint);
/**
* 彈出當(dāng)前本地引用幀溉苛,釋放所有本地引用
*
* @param env JNI接口指針
* @param result
*
* @return
*/
jobject (*PopLocalFrame)(JNIEnv *, jobject);
/**
* 為傳入的obj創(chuàng)建全局引用镜廉,obj可以是全局引用也可以是局部引用。全局引用需要調(diào)用DeleteGlobalRef來(lái)釋放
*
* @param env JNI接口指針
* @param obj 全局或局部引用
*
* @return 全局引用 or NULL(內(nèi)存不足)
*/
jobject (*NewGlobalRef)(JNIEnv *, jobject);
/**
* 釋放全局引用
*
* @param env JNI接口指針
* @param globalRef 全局引用
*/
void (*DeleteGlobalRef)(JNIEnv *, jobject);
/**
* 釋放局部引用
*
* @param env JNI接口指針
* @param localRef 局部引用
*/
void (*DeleteLocalRef)(JNIEnv *, jobject);
/**
* 判斷兩個(gè)引用是否同一java對(duì)象的引用
*
* @param env JNI接口指針
* @param ref1 引用1
* @param ref2 引用2
*
* @return JNI_TRUE:兩個(gè)引用指向同一個(gè)java對(duì)象
*/
jboolean (*IsSameObject)(JNIEnv *, jobject, jobject);
/**
* 為傳入的ref創(chuàng)建局部引用愚战,ref可以是全局引用也可以是局部引用
*
* @param env JNI接口指針
* @param ref 全局或局部引用
*
* @return 局部引用 or NULL
*/
jobject (*NewLocalRef)(JNIEnv *, jobject);
/**
* 確保當(dāng)前線程可以創(chuàng)建capacity個(gè)局部引用娇唯。在進(jìn)入本地方法時(shí),VM確奔帕幔可以可以創(chuàng)建最少16個(gè)局部引用
*
* @param env JNI接口指針
* @param capacity 局部引用個(gè)數(shù)
*
* @return 0:成功塔插,負(fù)數(shù):失敗
*
* @throws OutOfMemoryError 內(nèi)存不足
*/
jint (*EnsureLocalCapacity)(JNIEnv *, jint);
/**
* 創(chuàng)建一個(gè)新的java對(duì)象(不會(huì)調(diào)用對(duì)象的構(gòu)造方法)
*
* @param env JNI接口指針
* @param clazz 非數(shù)組class對(duì)象
*
* @return java對(duì)象
*
* @throws InstantiationException clazz是一個(gè)接口或抽象類
* @throws OutOfMemoryError 內(nèi)存不足
*/
jobject (*AllocObject)(JNIEnv *, jclass);
/**
* 構(gòu)造一個(gè)新的java對(duì)象,method ID指用以生成該類的構(gòu)造方法拓哟,method ID必須是通過(guò)GetMethodID()獲得
*
* @param env JNI接口指針
* @param clazz 非數(shù)組class對(duì)象
* @param ... 傳遞給構(gòu)造方法的參數(shù)
*
* @return java對(duì)象 or NULL(對(duì)象構(gòu)造失敗)
*
* @throws InstantiationException clazz是一個(gè)接口或抽象類
* @throws OutOfMemoryError 內(nèi)存不足
*/
jobject (*NewObject)(JNIEnv *, jclass, jmethodID, ...);
/**
* 構(gòu)造一個(gè)新的java對(duì)象想许,method ID指用以生成該類的構(gòu)造方法,method ID必須是通過(guò)GetMethodID()獲得
*
* @param env JNI接口指針
* @param clazz 非數(shù)組class對(duì)象
* @param args va_list結(jié)構(gòu),里面有傳遞給構(gòu)造方法的參數(shù)
*
* @return java對(duì)象 or NULL(對(duì)象構(gòu)造失敗)
*
* @throws InstantiationException clazz是一個(gè)接口或抽象類
* @throws OutOfMemoryError 內(nèi)存不足
*/
jobject (*NewObjectV)(JNIEnv *, jclass, jmethodID, va_list);
/**
* 構(gòu)造一個(gè)新的java對(duì)象伸刃,method ID指用以生成該類的構(gòu)造方法谎砾,method ID必須是通過(guò)GetMethodID()獲得
*
* @param env JNI接口指針
* @param clazz 非數(shù)組class對(duì)象
* @param args 參數(shù)數(shù)組,里面是傳遞給構(gòu)造方法的參數(shù)
*
* @return java對(duì)象 or NULL(對(duì)象構(gòu)造失敗)
*
* @throws InstantiationException clazz是一個(gè)接口或抽象類
* @throws OutOfMemoryError 內(nèi)存不足
*/
jobject (*NewObjectA)(JNIEnv *, jclass, jmethodID, jvalue *);
/**
* 返回對(duì)象對(duì)應(yīng)的class對(duì)象
*
* @param env JNI接口指針
* @param obj 非空java對(duì)象
*
* @return class對(duì)象
*/
jclass (*GetObjectClass)(JNIEnv *, jobject);
/**
* 判斷obj是否clazz的實(shí)例對(duì)象
*
* @param env JNI接口指針
* @param obj java對(duì)象
* @param clazz class對(duì)象
*
* @return
*/
jboolean (*IsInstanceOf)(JNIEnv *, jobject, jclass);
/**
* 返回非靜態(tài)方法的method ID
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param name 方法名
* @param sig 方法簽名
*
* @return 方法ID or NULL
*
* @throws NoSuchMethodError 找不到對(duì)應(yīng)的方法
* @throws ExceptionInInitializerError class初始化失敗
* @throws OutOfMemoryError 內(nèi)存不足
*/
jmethodID (*GetMethodID)(JNIEnv *, jclass, const char *, const char *);
/**
* Call<type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...);調(diào)用參數(shù)放到可變參數(shù)中
* Call<type>MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);調(diào)用參數(shù)放入jvalue數(shù)組
* Call<type>MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args);調(diào)用參數(shù)放入va_list結(jié)構(gòu)中
*
* 以上三組調(diào)用接口都是根據(jù) method ID調(diào)用java實(shí)例方法(非靜態(tài)方法)的接口捧颅,其中method ID是通過(guò)GetMethodID()獲取的
* 當(dāng)這些方法用于調(diào)用java對(duì)象的私有方法或構(gòu)造函數(shù)時(shí)景图,method ID必須從obj的真實(shí)類獲取,而不應(yīng)從其某個(gè)父類獲取
* <type>是方法的返回類型碉哑,三類接口間唯一的區(qū)別是methodID參數(shù)之后調(diào)用參數(shù)的不同
*
*
* @param env JNI接口指針
* @param obj java對(duì)象
* @param methodID 方法ID
* @param args 調(diào)用參數(shù)
*
* @return java方法返回結(jié)果
*
* @throws java方法中可能拋出的異常
*/
jobject (*CallObjectMethod)(JNIEnv *, jobject, jmethodID, ...);
jobject (*CallObjectMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jobject (*CallObjectMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
jboolean (*CallBooleanMethod)(JNIEnv *, jobject, jmethodID, ...);
jboolean (*CallBooleanMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jboolean (*CallBooleanMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
jbyte (*CallByteMethod)(JNIEnv *, jobject, jmethodID, ...);
jbyte (*CallByteMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jbyte (*CallByteMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
jchar (*CallCharMethod)(JNIEnv *, jobject, jmethodID, ...);
jchar (*CallCharMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jchar (*CallCharMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
jshort (*CallShortMethod)(JNIEnv *, jobject, jmethodID, ...);
jshort (*CallShortMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jshort (*CallShortMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
jint (*CallIntMethod)(JNIEnv *, jobject, jmethodID, ...);
jint (*CallIntMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jint (*CallIntMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
jlong (*CallLongMethod)(JNIEnv *, jobject, jmethodID, ...);
jlong (*CallLongMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jlong (*CallLongMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
jfloat (*CallFloatMethod)(JNIEnv *, jobject, jmethodID, ...);
jfloat (*CallFloatMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jfloat (*CallFloatMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
jdouble (*CallDoubleMethod)(JNIEnv *, jobject, jmethodID, ...);
jdouble (*CallDoubleMethodV)(JNIEnv *, jobject, jmethodID, va_list);
jdouble (*CallDoubleMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
void (*CallVoidMethod)(JNIEnv *, jobject, jmethodID, ...);
void (*CallVoidMethodV)(JNIEnv *, jobject, jmethodID, va_list);
void (*CallVoidMethodA)(JNIEnv *, jobject, jmethodID, jvalue *);
/**
* CallNonvirtual<type>Method(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);調(diào)用參數(shù)放到可變參數(shù)中
* CallNonvirtual<type>MethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args);調(diào)用參數(shù)放入jvalue數(shù)組
* CallNonvirtual<type>MethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args);調(diào)用參數(shù)放入va_list結(jié)構(gòu)中
*
* 以上三組調(diào)用接口都是根據(jù) method ID 和 class 調(diào)用java實(shí)例方法(非靜態(tài)方法)的接口挚币,其中method ID是基于clazz通過(guò)GetMethodID()獲取的
* <type>是方法的返回類型,三類接口間唯一的區(qū)別是methodID參數(shù)之后調(diào)用參數(shù)的不同
* 注意扣典,和Call<type>Method不同妆毕,如果子類重寫了父類的方法,Call<type>Method調(diào)用的是子類的方法贮尖,如果想調(diào)用父類的方法笛粘,
* 則需要用CallNonvirtual<type>Method,這個(gè)方法可以傳入父類的class和父類的method id湿硝,從而達(dá)到調(diào)用父類方法的效果
*
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param obj java對(duì)象
* @param methodID 方法ID
* @param args 調(diào)用參數(shù)
*
* @return java方法返回結(jié)果
*
* @throws java方法中可能拋出的異常
*/
jobject (*CallNonvirtualObjectMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jobject (*CallNonvirtualObjectMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jobject (*CallNonvirtualObjectMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
jboolean (*CallNonvirtualBooleanMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
jbyte (*CallNonvirtualByteMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jbyte (*CallNonvirtualByteMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jbyte (*CallNonvirtualByteMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
jchar (*CallNonvirtualCharMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jchar (*CallNonvirtualCharMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jchar (*CallNonvirtualCharMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
jshort (*CallNonvirtualShortMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jshort (*CallNonvirtualShortMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jshort (*CallNonvirtualShortMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
jint (*CallNonvirtualIntMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jint (*CallNonvirtualIntMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jint (*CallNonvirtualIntMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
jlong (*CallNonvirtualLongMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jlong (*CallNonvirtualLongMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jlong (*CallNonvirtualLongMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
jfloat (*CallNonvirtualFloatMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jfloat (*CallNonvirtualFloatMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jfloat (*CallNonvirtualFloatMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
jdouble (*CallNonvirtualDoubleMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
void (*CallNonvirtualVoidMethod)(JNIEnv *, jobject, jclass, jmethodID, ...);
void (*CallNonvirtualVoidMethodV)(JNIEnv *, jobject, jclass, jmethodID, va_list);
void (*CallNonvirtualVoidMethodA)(JNIEnv *, jobject, jclass, jmethodID, jvalue *);
/**
* 根據(jù)class對(duì)象獲取非靜態(tài)成員變量的field ID
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param name 變量名
* @param sig 變量簽名
*
* @return field ID or NULL
*
* @throws NoSuchFieldError 找不到對(duì)應(yīng)的變量ID
* @throws ExceptionInInitializerError class初始化失敗
* @throws OutOfMemoryError 內(nèi)存不足
*/
jfieldID (*GetFieldID)(JNIEnv *, jclass, const char *, const char *);
/**
* 根據(jù)field id取出對(duì)象中相應(yīng)的變量值薪前,field Id通過(guò)GetFieldID()獲取
*
* @param env JNI接口指針
* @param obj java對(duì)象
* @param fieldID 有效的field id
*
* @return 相應(yīng)的變量值
*/
jobject (*GetObjectField)(JNIEnv *, jobject, jfieldID);
jboolean (*GetBooleanField)(JNIEnv *, jobject, jfieldID);
jbyte (*GetByteField)(JNIEnv *, jobject, jfieldID);
jchar (*GetCharField)(JNIEnv *, jobject, jfieldID);
jshort (*GetShortField)(JNIEnv *, jobject, jfieldID);
jint (*GetIntField)(JNIEnv *, jobject, jfieldID);
jlong (*GetLongField)(JNIEnv *, jobject, jfieldID);
jfloat (*GetFloatField)(JNIEnv *, jobject, jfieldID);
jdouble (*GetDoubleField)(JNIEnv *, jobject, jfieldID);
/**
* 根據(jù)field id為相應(yīng)的變量設(shè)置新的值,field Id通過(guò)GetFieldID()獲取
*
* @param env JNI接口指針
* @param obj java對(duì)象
* @param fieldID 有效的field id
* @param value 要設(shè)置的值
*/
void (*SetObjectField)(JNIEnv *, jobject, jfieldID, jobject);
void (*SetBooleanField)(JNIEnv *, jobject, jfieldID, jboolean);
void (*SetByteField)(JNIEnv *, jobject, jfieldID, jbyte);
void (*SetCharField)(JNIEnv *, jobject, jfieldID, jchar);
void (*SetShortField)(JNIEnv *, jobject, jfieldID, jshort);
void (*SetIntField)(JNIEnv *, jobject, jfieldID, jint);
void (*SetLongField)(JNIEnv *, jobject, jfieldID, jlong);
void (*SetFloatField)(JNIEnv *, jobject, jfieldID, jfloat);
void (*SetDoubleField)(JNIEnv *, jobject, jfieldID, jdouble);
/**
* 返回靜態(tài)方法的method ID
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param name 方法名
* @param sig 方法簽名
*
* @return 方法ID or NULL
*
* @throws NoSuchMethodError 找不到對(duì)應(yīng)的方法
* @throws ExceptionInInitializerError class初始化失敗
* @throws OutOfMemoryError 內(nèi)存不足
*/
jmethodID (*GetStaticMethodID)(JNIEnv *, jclass, const char *, const char *);
/**
* CallStatic<type>Method(JNIEnv *env, jclass clazz, jmethodID methodID, ...);調(diào)用參數(shù)放到可變參數(shù)中
* CallStatic<type>MethodA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);調(diào)用參數(shù)放入jvalue數(shù)組
* CallStatic<type>MethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);調(diào)用參數(shù)放入va_list結(jié)構(gòu)中
*
* 以上三組調(diào)用接口都是根據(jù) method ID調(diào)用java靜態(tài)方法的接口关斜,其中method ID是通過(guò)GetStaticMethodID()獲取的
* method ID必須從clazz的真實(shí)類獲取示括,而不應(yīng)從其某個(gè)父類獲取
* <type>是方法的返回類型,三類接口間唯一的區(qū)別是methodID參數(shù)之后調(diào)用參數(shù)的不同
*
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param methodID 方法ID
* @param args 調(diào)用參數(shù)
*
* @return java方法返回結(jié)果
*
* @throws java方法中可能拋出的異常
*/
jobject (*CallStaticObjectMethod)(JNIEnv *, jclass, jmethodID, ...);
jobject (*CallStaticObjectMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jobject (*CallStaticObjectMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
jboolean (*CallStaticBooleanMethod)(JNIEnv *, jclass, jmethodID, ...);
jboolean (*CallStaticBooleanMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jboolean (*CallStaticBooleanMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
jbyte (*CallStaticByteMethod)(JNIEnv *, jclass, jmethodID, ...);
jbyte (*CallStaticByteMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jbyte (*CallStaticByteMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
jchar (*CallStaticCharMethod)(JNIEnv *, jclass, jmethodID, ...);
jchar (*CallStaticCharMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jchar (*CallStaticCharMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
jshort (*CallStaticShortMethod)(JNIEnv *, jclass, jmethodID, ...);
jshort (*CallStaticShortMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jshort (*CallStaticShortMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
jint (*CallStaticIntMethod)(JNIEnv *, jclass, jmethodID, ...);
jint (*CallStaticIntMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jint (*CallStaticIntMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
jlong (*CallStaticLongMethod)(JNIEnv *, jclass, jmethodID, ...);
jlong (*CallStaticLongMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jlong (*CallStaticLongMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
jfloat (*CallStaticFloatMethod)(JNIEnv *, jclass, jmethodID, ...);
jfloat (*CallStaticFloatMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jfloat (*CallStaticFloatMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
jdouble (*CallStaticDoubleMethod)(JNIEnv *, jclass, jmethodID, ...);
jdouble (*CallStaticDoubleMethodV)(JNIEnv *, jclass, jmethodID, va_list);
jdouble (*CallStaticDoubleMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
void (*CallStaticVoidMethod)(JNIEnv *, jclass, jmethodID, ...);
void (*CallStaticVoidMethodV)(JNIEnv *, jclass, jmethodID, va_list);
void (*CallStaticVoidMethodA)(JNIEnv *, jclass, jmethodID, jvalue *);
/**
* 根據(jù)class對(duì)象獲取靜態(tài)成員變量的field ID
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param name 變量名
* @param sig 變量簽名
*
* @return field ID or NULL
*
* @throws NoSuchFieldError 找不到對(duì)應(yīng)的變量ID
* @throws ExceptionInInitializerError class初始化失敗
* @throws OutOfMemoryError 內(nèi)存不足
*/
jfieldID (*GetStaticFieldID)(JNIEnv *, jclass, const char *, const char *);
/**
* 根據(jù)field id取出對(duì)象中相應(yīng)的變量值痢畜,field Id通過(guò)GetStaticFieldID()獲取
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param fieldID 有效的field id
*
* @return 相應(yīng)的靜態(tài)變量值
*/
jobject (*GetStaticObjectField)(JNIEnv *, jclass, jfieldID);
jboolean (*GetStaticBooleanField)(JNIEnv *, jclass, jfieldID);
jbyte (*GetStaticByteField)(JNIEnv *, jclass, jfieldID);
jchar (*GetStaticCharField)(JNIEnv *, jclass, jfieldID);
jshort (*GetStaticShortField)(JNIEnv *, jclass, jfieldID);
jint (*GetStaticIntField)(JNIEnv *, jclass, jfieldID);
jlong (*GetStaticLongField)(JNIEnv *, jclass, jfieldID);
jfloat (*GetStaticFloatField)(JNIEnv *, jclass, jfieldID);
jdouble (*GetStaticDoubleField)(JNIEnv *, jclass, jfieldID);
/**
* 根據(jù)field id為相應(yīng)的靜態(tài)變量設(shè)置新的值垛膝,field Id通過(guò)GetStaticFieldID()獲取
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param fieldID 有效的field id
* @param value 要設(shè)置的值
*/
void (*SetStaticObjectField)(JNIEnv *, jclass, jfieldID, jobject);
void (*SetStaticBooleanField)(JNIEnv *, jclass, jfieldID, jboolean);
void (*SetStaticByteField)(JNIEnv *, jclass, jfieldID, jbyte);
void (*SetStaticCharField)(JNIEnv *, jclass, jfieldID, jchar);
void (*SetStaticShortField)(JNIEnv *, jclass, jfieldID, jshort);
void (*SetStaticIntField)(JNIEnv *, jclass, jfieldID, jint);
void (*SetStaticLongField)(JNIEnv *, jclass, jfieldID, jlong);
void (*SetStaticFloatField)(JNIEnv *, jclass, jfieldID, jfloat);
void (*SetStaticDoubleField)(JNIEnv *, jclass, jfieldID, jdouble);
/**
* 創(chuàng)建一個(gè)新的java.lang.String對(duì)象
*
* @param env JNI接口指針
* @param unicodeChars 指向Unicode字符串的指針
* @param len Unicode字符串的長(zhǎng)度
*
* @return String對(duì)象 or NULL
*
* @throws OutOfMemoryError 內(nèi)存不足
*/
jstring (*NewString)(JNIEnv *, const jchar *, jsize);
/**
* 返回java.lang.String的長(zhǎng)度(Unicode字符數(shù))
*
* @param env JNI接口指針
* @param string String對(duì)象
*
* @return 長(zhǎng)度
*/
jsize (*GetStringLength)(JNIEnv *, jstring);
/**
* 返回指向Unicode字符數(shù)組的指針
* 該指針在調(diào)用ReleaseStringchars()前一直有效
* 如果isCopy非空,則在復(fù)制完成后將*isCopy設(shè)為JNI_TRUE丁稀。否則設(shè)為JNI_FALSE
*
* @param env JNI接口指針
* @param string String對(duì)象
* @param isCopy 指向boolean的指針
*
* @return 指向字符串的指針 or NULL
*/
const jchar *(*GetStringChars)(JNIEnv *, jstring, jboolean *);
/**
* 通知VM無(wú)需再訪問(wèn)chars
* chars是一個(gè)指針吼拥,通過(guò)GetStringChars()
*
* @param env JNI接口指針
* @param string String對(duì)象
* @param chars 指向字符串的指針
*/
void (*ReleaseStringChars)(JNIEnv *, jstring, const jchar *);
/**
* 根據(jù)UTF-8編碼的字符數(shù)組創(chuàng)建一個(gè)新的java.lang.String對(duì)象
*
* @param env JNI接口指針
* @param bytes 指向UTF-8字符串的指針
*
* @return String對(duì)象 or NULL
*
* @throws OutOfMemoryError 內(nèi)存不足
*/
jstring (*NewStringUTF)(JNIEnv *, const char *);
/**
* 返回字符串以UTF-8為編碼的字節(jié)數(shù)
*
* @param env JNI接口指針
* @param string String對(duì)象
*
* @return 字符串的UTF-8字節(jié)數(shù)
*/
jsize (*GetStringUTFLength)(JNIEnv *, jstring);
/**
* 返回指向UTF-8編碼字符數(shù)組的指針
* 該指針在調(diào)用ReleaseStringUTFChars()前一直有效
* 如果isCopy非空,則在復(fù)制完成后將*isCopy設(shè)為JNI_TRUE线衫。否則設(shè)為JNI_FALSE
*
* @param env JNI接口指針
* @param string String對(duì)象
* @param isCopy 指向boolean的指針
*
* @return 指向字符串的指針 or NULL
*/
const char *(*GetStringUTFChars)(JNIEnv *, jstring, jboolean *);
/**
* 通知VM無(wú)需再訪問(wèn)utf
* utf是一個(gè)指針凿可,通過(guò)GetStringUTFChars()
*
* @param env JNI接口指針
* @param string String對(duì)象
* @param utf 指向字符串的指針
*/
void (*ReleaseStringUTFChars)(JNIEnv *, jstring, const char *);
/**
* 獲取數(shù)組元素個(gè)數(shù)
*
* @param env JNI接口指針
* @param array java數(shù)組對(duì)象
*
* @return 數(shù)組長(zhǎng)度
*/
jsize (*GetArrayLength)(JNIEnv *, jarray);
/**
* 創(chuàng)建新的elementClass類型數(shù)組,所有元素初始值均設(shè)為initialElement
*
* @param env JNI接口指針
* @param length 數(shù)組大小
* @param elementClass 數(shù)組類型
* @param initialElement 初始值
*
* @return 數(shù)組對(duì)象 or NULL
*/
jobjectArray (*NewObjectArray)(JNIEnv *, jsize, jclass, jobject);
/**
* 獲取對(duì)象數(shù)組中指定index的值
*
* @param env JNI接口指針
* @param array java數(shù)組
* @param index 索引
*
* @return 索引對(duì)象的對(duì)象
*
* @throws ArrayIndexOutOfBoundsException
*/
jobject (*GetObjectArrayElement)(JNIEnv *, jobjectArray, jsize);
/**
* 設(shè)置對(duì)象數(shù)組中指定index的值
*
* @param env JNI接口指針
* @param array java數(shù)組
* @param index 索引
* @param value 新的值
*
* @throws ArrayIndexOutOfBoundsException
*/
void (*SetObjectArrayElement)(JNIEnv *, jobjectArray, jsize, jobject);
/**
* ArrayType New<PrimitiveType>Array(JNIEnv *env, jsize length);
* 創(chuàng)建基本類型數(shù)組對(duì)象
*
* @param env JNI接口指針
* @param length 數(shù)組大小
*
* @return 數(shù)組對(duì)象 or NULL
*/
jbooleanArray (*NewBooleanArray)(JNIEnv *, jsize);
jbyteArray (*NewByteArray)(JNIEnv *, jsize);
jcharArray (*NewCharArray)(JNIEnv *, jsize);
jshortArray (*NewShortArray)(JNIEnv *, jsize);
jintArray (*NewIntArray)(JNIEnv *, jsize);
jlongArray (*NewLongArray)(JNIEnv *, jsize);
jfloatArray (*NewFloatArray)(JNIEnv *, jsize);
jdoubleArray (*NewDoubleArray)(JNIEnv *, jsize);
/**
* NativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, jboolean *isCopy);
* 返回基本類型數(shù)組中的數(shù)據(jù)桶雀,通過(guò)返回的指針可以訪問(wèn)這些數(shù)據(jù),若虛擬機(jī)支持pinning唬复,則指針指向原始數(shù)組魂拦,否則指向原始數(shù)組的拷貝
* 返回的指針在Release<PrimitiveType>ArrayElements()調(diào)用前一直有效
* 數(shù)組用使用結(jié)束后座咆,調(diào)用Release<PrimitiveType>ArrayElements,并在調(diào)用參數(shù)中決定是否把修改提交給java
*
* @param env JNI接口指針
* @param array java數(shù)組
* @param isCopy 指向boolean的指針,若不為NULL苍姜,則執(zhí)行了復(fù)制設(shè)為JNI_TRUE,否則設(shè)為JNI_FALSE
*
* @return 指向數(shù)組元素的指針 or NULL
*/
jboolean *(*GetBooleanArrayElements)(JNIEnv *, jbooleanArray, jboolean *);
jbyte *(*GetByteArrayElements)(JNIEnv *, jbyteArray, jboolean *);
jchar *(*GetCharArrayElements)(JNIEnv *, jcharArray, jboolean *);
jshort *(*GetShortArrayElements)(JNIEnv *, jshortArray, jboolean *);
jint *(*GetIntArrayElements)(JNIEnv *, jintArray, jboolean *);
jlong *(*GetLongArrayElements)(JNIEnv *, jlongArray, jboolean *);
jfloat *(*GetFloatArrayElements)(JNIEnv *, jfloatArray, jboolean *);
jdouble *(*GetDoubleArrayElements)(JNIEnv *, jdoubleArray, jboolean *);
/**
* Release<PrimitiveType>ArrayElements
* 通知VM不再需要訪問(wèn)這些數(shù)組,根據(jù)mode參數(shù)的不同,將決定是否把數(shù)組的修改復(fù)制到源數(shù)組
*
* @param env JNI接口指針
* @param array java數(shù)組對(duì)象
* @param elems 指向數(shù)組元素的指針
* @param mode 釋放模式评疗,0:把數(shù)據(jù)復(fù)制回源數(shù)組并釋放elems緩沖區(qū),JNI_COMMIT:把數(shù)據(jù)復(fù)制回源數(shù)組但不釋放elems緩沖區(qū)茵烈,JNI_ABORT:不把數(shù)據(jù)復(fù)制回源數(shù)組百匆,釋放elems緩沖區(qū)
*/
void (*ReleaseBooleanArrayElements)(JNIEnv *, jbooleanArray, jboolean *, jint);
void (*ReleaseByteArrayElements)(JNIEnv *, jbyteArray, jbyte *, jint);
void (*ReleaseCharArrayElements)(JNIEnv *, jcharArray, jchar *, jint);
void (*ReleaseShortArrayElements)(JNIEnv *, jshortArray, jshort *, jint);
void (*ReleaseIntArrayElements)(JNIEnv *, jintArray, jint *, jint);
void (*ReleaseLongArrayElements)(JNIEnv *, jlongArray, jlong *, jint);
void (*ReleaseFloatArrayElements)(JNIEnv *, jfloatArray, jfloat *, jint);
void (*ReleaseDoubleArrayElements)(JNIEnv *, jdoubleArray, jdouble *, jint);
/**
* void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, NativeType *buf);
* 把基本類型數(shù)組拷貝到buf中
*
* @param env JNI接口指針
* @param array java數(shù)組
* @param start 開(kāi)始index
* @param len 拷貝長(zhǎng)度
* @param buf 目標(biāo)地址
*
* @throws ArrayIndexOutOfBoundsException
*/
void (*GetBooleanArrayRegion)(JNIEnv *, jbooleanArray, jsize, jsize, jboolean *);
void (*GetByteArrayRegion)(JNIEnv *, jbyteArray, jsize, jsize, jbyte *);
void (*GetCharArrayRegion)(JNIEnv *, jcharArray, jsize, jsize, jchar *);
void (*GetShortArrayRegion)(JNIEnv *, jshortArray, jsize, jsize, jshort *);
void (*GetIntArrayRegion)(JNIEnv *, jintArray, jsize, jsize, jint *);
void (*GetLongArrayRegion)(JNIEnv *, jlongArray, jsize, jsize, jlong *);
void (*GetFloatArrayRegion)(JNIEnv *, jfloatArray, jsize, jsize, jfloat *);
void (*GetDoubleArrayRegion)(JNIEnv *, jdoubleArray, jsize, jsize, jdouble *);
/**
* void Set<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, const NativeType *buf);
* 把buf中的內(nèi)容拷貝回?cái)?shù)組中
*
* @param env JNI接口指針
* @param array java數(shù)組
* @param start 開(kāi)始index
* @param len 拷貝長(zhǎng)度
* @param buf 源數(shù)據(jù)
*
* @throws ArrayIndexOutOfBoundsException
*/
void (*SetBooleanArrayRegion)(JNIEnv *, jbooleanArray, jsize, jsize, const jboolean *);
void (*SetByteArrayRegion)(JNIEnv *, jbyteArray, jsize, jsize, const jbyte *);
void (*SetCharArrayRegion)(JNIEnv *, jcharArray, jsize, jsize, const jchar *);
void (*SetShortArrayRegion)(JNIEnv *, jshortArray, jsize, jsize, const jshort *);
void (*SetIntArrayRegion)(JNIEnv *, jintArray, jsize, jsize, const jint *);
void (*SetLongArrayRegion)(JNIEnv *, jlongArray, jsize, jsize, const jlong *);
void (*SetFloatArrayRegion)(JNIEnv *, jfloatArray, jsize, jsize, const jfloat *);
void (*SetDoubleArrayRegion)(JNIEnv *, jdoubleArray, jsize, jsize, const jdouble *);
/**
* 為clazz類注冊(cè)本地方法
*
* @param env JNI接口指針
* @param clazz class對(duì)象
* @param methods clazz類中的本地方法,指向方法數(shù)組
* @param nMethods 本地方法個(gè)數(shù)
*
* @return 0:成功呜投, 負(fù)數(shù):失敗
*
* @throws NoSuchMethodError
*/
jint (*RegisterNatives)(JNIEnv *, jclass, const JNINativeMethod *, jint);
/**
* 取消clazz類本地方法的注冊(cè)
*
* @param env JNI接口指針
* @param clazz class對(duì)象
*
* @return 0:成功加匈, 負(fù)數(shù):失敗
*/
jint (*UnregisterNatives)(JNIEnv *, jclass);
/**
* 進(jìn)入與obj所引用的Java對(duì)象相關(guān)聯(lián)的監(jiān)控,obj 必須為非空
*
* @param env JNI接口指針
* @param obj java對(duì)象 或 class對(duì)象
*
* @return 0:成功仑荐, 負(fù)數(shù):失敗
*/
jint (*MonitorEnter)(JNIEnv *, jobject);
/**
* 退出與obj所引用的Java對(duì)象相關(guān)聯(lián)的監(jiān)控雕拼,obj 必須為非空
* 當(dāng)前線程必須是與obj所引用的Java對(duì)象相關(guān)聯(lián)的監(jiān)控程序的所有者
* 監(jiān)控程序次數(shù)的計(jì)數(shù)器減 1。如果計(jì)數(shù)器的值變?yōu)?0粘招,則釋放當(dāng)前線程的監(jiān)控程序
*
* @param env JNI接口指針
* @param obj java對(duì)象 或 class對(duì)象
*
* @return 0:成功啥寇, 負(fù)數(shù):失敗
*/
jint (*MonitorExit)(JNIEnv *, jobject);
/**
* 獲取當(dāng)前線程關(guān)聯(lián)的Java VM接口
*
* @param env JNI接口指針
* @param vm java VM接口指針
*
* @return 0:成功, 負(fù)數(shù):失敗
*/
jint (*GetJavaVM)(JNIEnv *, JavaVM **);
/**
* 從start index開(kāi)始洒扎,拷貝len個(gè)Unicode字符到buf
*
* @param env JNI接口指針
* @param str string對(duì)象
* @param start 開(kāi)始index
* @param len 拷貝長(zhǎng)度
* @param buf 目標(biāo)地址
*
* @throws StringIndexOutOfBoundsException
*/
void (*GetStringRegion)(JNIEnv *, jstring, jsize, jsize, jchar *);
/**
* 從start index開(kāi)始辑甜,取出len個(gè)Unicode字符轉(zhuǎn)換為UTF-8編碼后拷貝到buf
*
* @param env JNI接口指針
* @param str string對(duì)象
* @param start 開(kāi)始index
* @param len 拷貝長(zhǎng)度
* @param buf 目標(biāo)地址
*
* @throws StringIndexOutOfBoundsException
*/
void (*GetStringUTFRegion)(JNIEnv *, jstring, jsize, jsize, char *);
/**
* 與Get/Release<primitivetype>ArrayElements方法非常相似,在這個(gè)方法中VM盡量返回指向原始數(shù)組的指針
*
* @since JDK/JRE 1.2
*
* @param env JNI接口指針
* @param array java數(shù)組
* @param isCopy 指向boolean的指針逊笆,若不為NULL栈戳,則執(zhí)行了復(fù)制設(shè)為JNI_TRUE,否則設(shè)為JNI_FALSE
*
* @return 指向數(shù)組元素的指針 or NULL
*/
void *(*GetPrimitiveArrayCritical)(JNIEnv *, jarray, jboolean *);
void (*ReleasePrimitiveArrayCritical)(JNIEnv *, jarray, void *, jint);
/**
* 與Get/ReleaseStringChars方法非常相似难裆,在這個(gè)方法中VM盡量返回指向原始字符串的指針
*
* @since JDK/JRE 1.2
*
* @param env JNI接口指針
* @param string String對(duì)象
* @param isCopy 指向boolean的指針
*
* @return 指向字符串的指針 or NULL
*/
const jchar *(*GetStringCritical)(JNIEnv *, jstring, jboolean *);
void (*ReleaseStringCritical)(JNIEnv *, jstring, const jchar *);
/**
* 為傳入的obj創(chuàng)建弱全局引用
* 弱全局引用不會(huì)阻止VM釋放所引用的對(duì)象子檀,程序中可以通過(guò)使用IsSameObject比較弱全局引用和NULL來(lái)確認(rèn)所引用的對(duì)象是否被釋放
*
* @param env JNI接口指針
* @param obj 全局或局部引用
*
* @return 弱全局引用 or NULL
*/
jweak (*NewWeakGlobalRef)(JNIEnv *, jobject);
/**
* 刪除弱全局引用
*
* @param env JNI接口指針
* @param obj 弱全局引用
*/
void (*DeleteWeakGlobalRef)(JNIEnv *, jweak);
/**
* 判斷是否有未處理異常
*
* @param env JNI接口指針
*
* @return JNI_TRUE表示有未處理異常,否則為JNI_FALSE
*/
jboolean (*ExceptionCheck)(JNIEnv *);
/**
* 創(chuàng)建并返回java.nio.ByteBuffer對(duì)象乃戈,該對(duì)象引用以address為開(kāi)始地址褂痰,大小為capacity的內(nèi)存塊
*
* @since JDK/JRE 1.4
*
* @param env JNI接口指針
* @param address 開(kāi)始地址
* @param capacity 內(nèi)存大小
*
* @return Jjava.nio.ByteBuffer or NULL
*
* @throws OutOfMemoryError
*/
jobject (*NewDirectByteBuffer)(JNIEnv *, void *, jlong);
/**
* 根據(jù)java.nio.ByteBuffer對(duì)象,獲取相應(yīng)的內(nèi)存數(shù)據(jù)并返回開(kāi)始地址
*
* @since JDK/JRE 1.4
*
* @param env JNI接口指針
* @param buf java.nio.ByteBuffer對(duì)象
*
* @return 數(shù)據(jù)的開(kāi)始地址 or NULL
*/
void *(*GetDirectBufferAddress)(JNIEnv *, jobject);
/**
* 根據(jù)java.nio.ByteBuffer對(duì)象症虑,獲取相應(yīng)的內(nèi)存數(shù)據(jù)的大小
*
* @since JDK/JRE 1.4
*
* @param env JNI接口指針
* @param buf java.nio.ByteBuffer對(duì)象
*
* @return 數(shù)據(jù)大小 or -1
*/
jlong (*GetDirectBufferCapacity)(JNIEnv *, jobject);
/**
* 獲取java對(duì)象的引用類型缩歪,可能的返回值有:
* JNIInvalidRefType
* JNILocalRefType:局部引用
* JNIGlobalRefType:全局引用
* JNIWeakGlobalRefType :全局弱若引用
*
* @since JDK/JRE 1.6
*
* @param env JNI接口指針
* @param obj java對(duì)象的引用
*
* @return 引用類型
*/
jobjectRefType (*GetObjectRefType)(JNIEnv *, jobject);