日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JNI教程与技术手册

發布時間:2024/1/23 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JNI教程与技术手册 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載:https://blog.csdn.net/shensky711/article/details/52806794

概述

對于JNI,有些童鞋在沒有接觸過的時候,可能會覺得比較復雜,但是其實當你真正去了解、去使用的時候,就會發現JNI的使用還是比較簡單的,JNI本身提供了一系列的API讓我們可以在native方法中操作java。JNI的使用無非也就是使用這些接口和java交互。這幾天在學習JNI接口的時候,發現網上搜索的JNI的中文雖然不少,但是很多都是零零碎碎的小例子,有一些官方文檔的翻譯,但要么是不全面,要么是資料比較舊了,干脆自己根據java native interface specification整理了一份技術資料。當然,很多時候看中文資料是詞不達意的,如果文中有疑問的地方歡迎指出,或者翻閱原文
首先,JNI是一個本地編程接口。它允許運行在Java虛擬機的Java代碼與用其他語言(如C,C++和匯編)編寫的庫交互

JNI最大的好處是JNI不受Java虛擬機實現方式的限制,因此,Java虛擬機廠商添加JNI的支持并不會影響虛擬機其他功能模塊。native代碼只需要編寫一遍,就可以在所有支持JNI的虛擬機上工作。

通過JNI,你可以在native代碼中:

  • 創建、檢查或者更新java對象
  • 調用java方法
  • 捕捉和拋出異常
  • 加載class和獲取class信息
  • 運行時類型檢查

JNI接口函數和指針

本地代碼通過JNI函數(接口指針,接口指針是指針的指針)來訪問java VM.

JNI接口指針只在當前線程有效,因此在native方法中不要跨線程傳遞接口指針參數。native方法接收JNI接口指針參數,VM確保在同一個線程中調用native方法的時候,傳遞同一個接口指針給接口指針給native方法。然而,native方法可能在Java中的不同線程中調用,所以native方法接收到的接口指針可能就是不一樣的。

編譯、加載和鏈接本地方法

編譯

Java VM是多線程的,所以native libraries應該多線程編譯器來進行編譯和鏈接。例如使用Sun Studio compiler編譯器的時候,要為C++代碼添加-mt標記;使用GNU gcc compiler的時候,需添加-D_REENTRANT或-D_POSIX_C_SOURCE

加載

native庫通過System.loadLibrary方法進行加載。如:

package pkg;class Cls {native double f(int i, String s);static {System.loadLibrary("pkg_Cls");} }

系統會對library名會進行轉換,在不同平臺上有不同的轉換方式,例如,Solaris系統轉換pkg_Cls為libpkg_Cls.so,而Win32系統轉換pkg_Cls為pkg_Cls.dll

鏈接

如果系統不支持動態鏈接,那么所有本地方法需要預鏈接到虛擬機,這種情況下,VM已經完成System.loadLibrary了。程序猿也可以調用JNI函數RegisterNatives()來注冊該類關聯的本地方法

Native Method 命令解析

一個本地方法名有以下幾個組成部分:

? 1.前綴Java_

? 2.完整雷鳴(類名中的.用_的代替)

? 3.下劃線_

? 4.方法名(方法名中的特殊字符需要轉義)

? 5.參數簽名(非必須,有重載方法的時候才需要),如果有重載的本地方法,需要再添加兩個下劃線__,然后在添加方法簽名(由java字段描述符描述,用_代替描述符中的包名分割/符,簽名中的特殊字符需要轉義)

Unicode轉義字符

轉義符說明
_0XXXX一個Unicode字符XXXX。注意小寫是用來表示非ascii Unicode字符, 如:_0abcd與_0ABCD不相同
_1字符_
_2參數簽名中的字符;
_3參數簽名中的字符[

Java字段描述符

Java類型符號
BooleanZ
·ByteB
CharC
ShortS
IntI
LongJ
Float?F
DoubleD
VoidV
數組[,如:int[]->[I, int[][]->[[I, Thread[]->[Ljava/lang/Thread;
objects以“L”開頭,以“;”結尾,中間是用"/"隔開的包及類名,比如:Ljava/lang/String;如果是嵌套類,則用$來表示嵌套。例如"(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"

舉例

package pkg;class Cls {//對應本地方法名: Java_pkg_Cls_f__ILjava_lang_String_2native double f(int i, String s);...}

Native 方法參數

  • JNI接口指針是native方法的第一個參數,JNI接口指針的類型是JNIEnv。
  • 第二個參數取決于native method是否靜態方法,如果是非靜態方法,那么第二個參數是對對象的引用,如果是靜態方法,則第二個參數是對它的class類的引用
  • 剩下的參數跟Java方法參數--對應
package pkg;class Cls { native double f(int i, String s);...} //注意,c和c++在使用JNI接口的時候有點不一致,請仔細觀察通過env調用接口的調用方式 //C版本 jdouble Java_pkg_Cls_f__ILjava_lang_String_2 (JNIEnv *env, /* interface pointer */jobject obj, /* "this" pointer */jint i, /* argument #1 */jstring s) {/* 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對象引用

  • 基本類型(如整型、字符等)在Java和native之間是采用值傳遞
  • Java對象采用的是引用傳遞

虛擬機必須保持已傳遞給native的對象的引用,以使這些對象不被垃圾回收器回收。native code也必須有一種方法通知虛擬機它不再需要某個對象,并且垃圾收集器必須能夠將其回收。

全局引用、局部引用和弱全局應用

JNI中使用的引用可以劃分為三類:全局引用、局部引用和弱全局引用。局部引用在方法調用的時候有效,在方法調用結束之后會自動釋放。全局引用會一直可用,直到顯示地對其進行釋放。弱全局引用跟全局引用的區別是弱全局引用持有的java對象可以被VM進行回收,所以才是用弱全局引用前,我們需要對其進行檢測,看它對應的對象是否被回收了。

對象是作為局部引用傳遞給native方法的,所有通過JNIEnv方法(也就是JNI提供的API)返回的java對象都是局部引用。JNI允許程序從局部引用創建一個全局引用。JNIEnv的方法既可以接收全局引用也可以接收局部引用。一個native方法既可以返回局部引用也可以返回全局引用。

大多數情況下,在方法調用結束之后,我們依賴VMq幫我們釋放所有局部引用,但是以下幾種情況下,我們應該顯式地釋放局部引用:

  • 方法中創建了一個比較大的java對象的,并持有其局部引用,使用完之后,如果接下來都不再需要使用了,如果仍然不對他進行釋放的話,在方法結束之前,這個對象都不會進行釋放,這樣會對資源造成浪費
  • JNI會將創建的局部引用都存儲在一個局部引用表中,如果這個表超過了最大容量限制,就會造成局部引用表溢出,使程序崩潰。比如在一個循環中創建局部引用,最好在每一輪循環中釋放局部引用,否則隨著循環次數增加,很可能就內存溢出了

局部引用僅僅在其創建的線程內有效,native代碼不能跨線程傳遞局部引用。

訪問字段和方法

JNI允許native代碼訪問對象的成員以及調用它的方法,通過兩個步驟即可實現訪問,比如,我們需要調用cls中的f方法:

jmethodID mid = env->GetMethodID(cls, "f", "(ILjava/lang/String;)D"); //mid可以重復使用

jdouble result = env->CallDoubleMethod(obj, mid, 10, str);

但是需要注意的是,字段ID或方法ID并不能防止VM卸載該類。當類被卸載后,方法ID和字段ID將變成不可用的。因此,我們需要確保:

-持有class的引用,讓它不被卸載,或者

-重新獲取方法id或者字段id

程序錯誤檢測

JNI不對空指針或非法參數類型等錯誤進行檢測,因為:

  • 檢查所有可能的錯誤會降低方法執行的性能
  • 在很多時候,沒有足夠的運行時信息去進行檢測

程序員不得傳遞一個非法指針或者錯誤的類型給JNI函數,否則可能會導致系統異常或虛擬機泵擴

Java異常

JNI允許本地方法拋出處理任何異常,也可以處理Java中跑出的異常,剩下沒有處理的異常會繼續給VM處理

異常和錯誤碼

大多數情況下,JNI提供的方法通過返回錯誤碼或者拋出Java異常來處理錯誤,因此,程序中可以:

  • 檢查JNI函數返回值
  • 調用ExceptionOccurred()方法,獲取方法中拋出的異常

有兩種情況下,程序需要優先檢測java異常而不是先檢測返回碼

  • 調用JNI調用Java方法的時候,需要ExceptionOccurred()檢測是否在Java方法中拋出了異常
  • 一些訪問數組的方法,它不返回錯誤碼,但是會拋出ArrayIndexOutOfBoundsException或者ArrayStoreException異常

異常處理

有兩種方法可以在本地方法中處理異常

  • 檢測到異常的時候立即返回,異常將會在調用該本地代碼的地方拋出
  • 在本地方法中調用ExceptionClear()清除異常,處理接下來的邏輯

異常拋出時,本地方法需清除異常后,才能繼續調用其它JNI接口方法,有異常發生后,只有以下方法才能被安全調用:

? ExceptionOccurred()
? ExceptionDescribe()
? ExceptionClear()
? ExceptionCheck()
? ReleaseStringChars()
? ReleaseStringUTFChars()
? ReleaseStringCritical()
? Release<Type>ArrayElements()
? ReleasePrimitiveArrayCritical()
? DeleteLocalRef()
? DeleteGlobalRef()
? DeleteWeakGlobalRef()
? MonitorExit()
? PushLocalFrame()
? PopLocalFrame()

原始類型

Java類型native類型描述
booleanjbooleanunsigned 8 bits
bytejbytesigned 8 bits
charjcharunsigned 16 bits
short?jshortsigned 16 bits
intjintsigned 32 bits
long?jlongsigned 64 bits
float?jfloat32 bits
doublejdouble64 bits
void?voidN/A

JNI中還定義了以下兩個宏定義方便使用:

#define JNI_FALSE 0 #define JNI_TRUE 1

引用類型

JNI為不同的java對象提供了不同的引用類型,JNI引用類型如下:

在c里面,所有JNI引用類型其實都是jobject

字段和方法ID

在C中,字段和方法ID是一個指向結構體的指針

struct _jfieldID; /* opaque structure*/ typedef struct _jfieldID *jfieldID; /*field IDs*/ struct _jmethodID; /*opaque structure*/ typedef struct _jmethodID *jmethodID; /*method IDs*/

值類型

值類型jvalue是一個聯合體結構,定義如下:

typedef union jvalue {jboolean z;jbyte b;jchar c;jint i;jlong j;jfloat f;jdouble d;jobject l; } jvalue;

簽名類型描述

請參考:java字段描述符?

如:

//方法簽名為:(ILjava/lang/String;[I)J long f (int n, String s, int[] arr);

UTF-8字符


JNI的 UTF-8與標準的 UTF-8格式有兩個區別:

空字符(char)0使用雙字節格式編碼,而不是單字節編碼,所以Java虛擬機的UTF-8字符串不可能有嵌入的空值。
只使用單字節、雙字節和三字節編碼格式,不支持標準的四字節編碼,用two-times-three-byte格式代替
JNI接口函數
在下面的說明中,必須說明JNI函數必須接受一個非空對象,你必須保證傳入的參數不為空,JNI函數不需要再對它進行空指針判斷


返回碼說明

#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 */
?

接口詳細


? ? /**
? ? ?* 返回本地方法接口的版本
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?*
? ? ?* @return 高16位返回主版本號,低16位返回次版本號,如在JDK/JRE 1.6中,返回0x00010006。也有可能返回 JNI_EDETACHED 和 JNI_EVERSION 錯誤碼
? ? ?*/
? ? jint (*GetVersion)(JNIEnv *);


? ? /**
? ? ?* 從二進制的.class的數據緩沖區中加載類
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param name UTF8編碼的需要加載的類的名字
? ? ?* @param loader 類加載器
? ? ?* @param buf 包含.class字節碼的數組
? ? ?* @param bufLen 長度
? ? ?*
? ? ?* @return class對象或NULL
? ? ?*
? ? ?* @throws ClassFormatError 不是有效的class數據
? ? ?* @throws ClassCircularityError 類或接口是自身的父類或自身繼承了該接口
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?* @throws SecurityException 如果該類是屬于java包的
? ? ?*/
? ? jclass (*DefineClass)(JNIEnv *, const char *, jobject, const jbyte *, jsize);


? ? /**
? ? ?* 用于加載本地定義的類
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param name 完整的包名("/"代替".") 或 數組類型字段描述("["開頭,緊跟簽名描述),如"java/lang/String" for java.lang.String, "[Ljava/lang/Object;" for java.lang.Object[]
? ? ?*
? ? ?* @return class對象或NULL
? ? ?*
? ? ?* @throws ClassFormatError 不是有效的class數據
? ? ?* @throws ClassCircularityError 類或接口是自身的父類或自身繼承了該接口
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?* @throws NoClassDefFoundError 找不到name對應的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對象
? ? ?*
? ? ?* @return 方法ID
? ? ?*/
? ? jmethodID (*FromReflectedMethod)(JNIEnv *, jobject);


? ? /**
? ? ?* 從java.lang.reflect.Field獲取field ID
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param field java.lang.reflect.Field對象
? ? ?*
? ? ?* @return field ID
? ? ?*/
? ? jfieldID (*FromReflectedField)(JNIEnv *, jobject);


? ? /**
? ? ?* 從method ID獲取 java.lang.reflect.Method 或 java.lang.reflect.Constructor 對象
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param cls 該方法的類對象
? ? ?* @param methodID 方法ID
? ? ?* @param isStatic 是否靜態方法
? ? ?*
? ? ?* @return java.lang.reflect.Method 或 java.lang.reflect.Constructor 對象
? ? ?*
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jobject (*ToReflectedMethod)(JNIEnv *, jclass, jmethodID, jboolean);


? ? /**
? ? ?* 如果clazz不是class對象或接口,則返回該class的超類
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?*
? ? ?* @return 返回輸入類的父類 或 NULL
? ? ?*/
? ? jclass (*GetSuperclass)(JNIEnv *, jclass);


? ? /**
? ? ?* class1是否可以安全地轉換為class2,以下三種情況會返回TRUE
? ? ?* 1. 當class1和class2是同一個java class的引用
? ? ?* 2. class1是class2的子類
? ? ?* 3. class2是class1的某個接口
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz1 class1
? ? ?* @param clazz2 class2
? ? ?*
? ? ?* @return JNI_TRUE or JNI_FALSE
? ? ?*/
? ? jboolean (*IsAssignableFrom)(JNIEnv *, jclass, jclass);


? ? /**
? ? ?* 根據 field ID 獲取 java.lang.reflect.Field 對象
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param cls 該方法的類對象
? ? ?* @param fieldID 字段ID
? ? ?* @param isStatic 是否靜態變量
? ? ?*
? ? ?* @return java.lang.reflect.Field 對象
? ? ?*
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jobject (*ToReflectedField)(JNIEnv *, jclass, jfieldID, jboolean);


? ? /**
? ? ?* 拋出異常
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj java.lang.Throwable 對象
? ? ?*
? ? ?* @return 0:成功, 負數:失敗
? ? ?*
? ? ?* @throws Throwable
? ? ?*/
? ? jint (*Throw)(JNIEnv *, jthrowable);


? ? /**
? ? ?* 根據clazz和message構造一個異常對象,并將它拋出
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz java.lang.Throwable的子類
? ? ?* @param message 錯誤信息
? ? ?*
? ? ?* @return 0:成功, 負數:失敗
? ? ?*
? ? ?* @throws Throwable
? ? ?*/
? ? jint (*ThrowNew)(JNIEnv *, jclass, const char *);


? ? /**
? ? ?* 判斷是否有異常拋出,在調用ExceptionClear()或java代碼處理了exception之前,都可以用這個方法判斷是否有異常
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?*
? ? ?* @return 異常對象 or NULL
? ? ?*/
? ? jthrowable (*ExceptionOccurred)(JNIEnv *);


? ? /**
? ? ?* 打印異常信息
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?*/
? ? void (*ExceptionDescribe)(JNIEnv *);


? ? /**
? ? ?* 清除所有已拋出的異常
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?*/
? ? void (*ExceptionClear)(JNIEnv *);


? ? /**
? ? ?* 拋出致命錯誤并且不希望虛擬機進行恢復。無返回值
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param msg 錯誤信息
? ? ?*/
? ? void (*FatalError)(JNIEnv *, const char *);


? ? /**
? ? ?* 創建一個新的本地引用幀
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param capacity 容量
? ? ?*
? ? ?* @return 0:成功,負數:失敗
? ? ?*
? ? ?* @throws OutOfMemoryError
? ? ?*/
? ? jint (*PushLocalFrame)(JNIEnv *, jint);


? ? /**
? ? ?* 彈出當前本地引用幀,釋放所有本地引用
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param result
? ? ?*
? ? ?* @return
? ? ?*/
? ? jobject (*PopLocalFrame)(JNIEnv *, jobject);


? ? /**
? ? ?* 為傳入的obj創建全局引用,obj可以是全局引用也可以是局部引用。全局引用需要調用DeleteGlobalRef來釋放
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj 全局或局部引用
? ? ?*
? ? ?* @return 全局引用 or NULL(內存不足)
? ? ?*/
? ? jobject (*NewGlobalRef)(JNIEnv *, jobject);


? ? /**
? ? ?* 釋放全局引用
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param globalRef 全局引用
? ? ?*/
? ? void (*DeleteGlobalRef)(JNIEnv *, jobject);


? ? /**
? ? ?* 釋放局部引用
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param localRef 局部引用
? ? ?*/
? ? void (*DeleteLocalRef)(JNIEnv *, jobject);


? ? /**
? ? ?* 判斷兩個引用是否同一java對象的引用
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param ref1 引用1
? ? ?* @param ref2 引用2
? ? ?*
? ? ?* @return JNI_TRUE:兩個引用指向同一個java對象
? ? ?*/
? ? jboolean (*IsSameObject)(JNIEnv *, jobject, jobject);


? ? /**
? ? ?* 為傳入的ref創建局部引用,ref可以是全局引用也可以是局部引用
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param ref 全局或局部引用
? ? ?*
? ? ?* @return 局部引用 or NULL
? ? ?*/
? ? jobject (*NewLocalRef)(JNIEnv *, jobject);


? ? /**
? ? ?* 確保當前線程可以創建capacity個局部引用。在進入本地方法時,VM確保可以可以創建最少16個局部引用
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param capacity 局部引用個數
? ? ?*
? ? ?* @return 0:成功,負數:失敗
? ? ?*
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jint (*EnsureLocalCapacity)(JNIEnv *, jint);


? ? /**
? ? ?* 創建一個新的java對象(不會調用對象的構造方法)
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz 非數組class對象
? ? ?*
? ? ?* @return java對象
? ? ?*
? ? ?* @throws InstantiationException clazz是一個接口或抽象類
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jobject (*AllocObject)(JNIEnv *, jclass);


? ? /**
? ? ?* 構造一個新的java對象,method ID指用以生成該類的構造方法,method ID必須是通過GetMethodID()獲得
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz 非數組class對象
? ? ?* @param ... 傳遞給構造方法的參數
? ? ?*
? ? ?* @return java對象 or NULL(對象構造失敗)
? ? ?*
? ? ?* @throws InstantiationException clazz是一個接口或抽象類
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jobject (*NewObject)(JNIEnv *, jclass, jmethodID, ...);


? ? /**
? ? ?* 構造一個新的java對象,method ID指用以生成該類的構造方法,method ID必須是通過GetMethodID()獲得
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz 非數組class對象
? ? ?* @param args va_list結構,里面有傳遞給構造方法的參數
? ? ?*
? ? ?* @return java對象 or NULL(對象構造失敗)
? ? ?*
? ? ?* @throws InstantiationException clazz是一個接口或抽象類
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jobject (*NewObjectV)(JNIEnv *, jclass, jmethodID, va_list);


? ? /**
? ? ?* 構造一個新的java對象,method ID指用以生成該類的構造方法,method ID必須是通過GetMethodID()獲得
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz 非數組class對象
? ? ?* @param args 參數數組,里面是傳遞給構造方法的參數
? ? ?*
? ? ?* @return java對象 or NULL(對象構造失敗)
? ? ?*
? ? ?* @throws InstantiationException clazz是一個接口或抽象類
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jobject (*NewObjectA)(JNIEnv *, jclass, jmethodID, jvalue *);


? ? /**
? ? ?* 返回對象對應的class對象
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj 非空java對象
? ? ?*
? ? ?* @return class對象
? ? ?*/
? ? jclass (*GetObjectClass)(JNIEnv *, jobject);


? ? /**
? ? ?* 判斷obj是否clazz的實例對象
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj java對象
? ? ?* @param clazz class對象
? ? ?*
? ? ?* @return
? ? ?*/
? ? jboolean (*IsInstanceOf)(JNIEnv *, jobject, jclass);


? ? /**
? ? ?* 返回非靜態方法的method ID
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param name 方法名
? ? ?* @param sig 方法簽名
? ? ?*
? ? ?* @return 方法ID or NULL
? ? ?*
? ? ?* @throws NoSuchMethodError 找不到對應的方法
? ? ?* @throws ExceptionInInitializerError class初始化失敗
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jmethodID (*GetMethodID)(JNIEnv *, jclass, const char *, const char *);


? ? /**
? ? ?* Call<type>Method(JNIEnv *env, jobject obj, jmethodID methodID, ...);調用參數放到可變參數中
? ? ?* Call<type>MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);調用參數放入jvalue數組
? ? ?* Call<type>MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args);調用參數放入va_list結構中
? ? ?*
? ? ?* 以上三組調用接口都是根據 method ID調用java實例方法(非靜態方法)的接口,其中method ID是通過GetMethodID()獲取的
? ? ?* 當這些方法用于調用java對象的私有方法或構造函數時,method ID必須從obj的真實類獲取,而不應從其某個父類獲取
? ? ?* <type>是方法的返回類型,三類接口間唯一的區別是methodID參數之后調用參數的不同
? ? ?*
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj java對象
? ? ?* @param methodID 方法ID
? ? ?* @param args 調用參數
? ? ?*
? ? ?* @return java方法返回結果
? ? ?*
? ? ?* @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, ...);調用參數放到可變參數中
? ? ?* CallNonvirtual<type>MethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, const jvalue *args);調用參數放入jvalue數組
? ? ?* CallNonvirtual<type>MethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args);調用參數放入va_list結構中
? ? ?*
? ? ?* 以上三組調用接口都是根據 method ID 和 class 調用java實例方法(非靜態方法)的接口,其中method ID是基于clazz通過GetMethodID()獲取的
? ? ?* <type>是方法的返回類型,三類接口間唯一的區別是methodID參數之后調用參數的不同
? ? ?* 注意,和Call<type>Method不同,如果子類重寫了父類的方法,Call<type>Method調用的是子類的方法,如果想調用父類的方法,
? ? ?* 則需要用CallNonvirtual<type>Method,這個方法可以傳入父類的class和父類的method id,從而達到調用父類方法的效果
? ? ?*
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param obj java對象
? ? ?* @param methodID 方法ID
? ? ?* @param args 調用參數
? ? ?*
? ? ?* @return java方法返回結果
? ? ?*
? ? ?* @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 *);


? ? /**
? ? ?* 根據class對象獲取非靜態成員變量的field ID
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param name 變量名
? ? ?* @param sig 變量簽名
? ? ?*
? ? ?* @return field ID or NULL
? ? ?*
? ? ?* @throws NoSuchFieldError 找不到對應的變量ID
? ? ?* @throws ExceptionInInitializerError class初始化失敗
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jfieldID (*GetFieldID)(JNIEnv *, jclass, const char *, const char *);


? ? /**
? ? ?* 根據field id取出對象中相應的變量值,field Id通過GetFieldID()獲取
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj java對象
? ? ?* @param fieldID 有效的field id
? ? ?*
? ? ?* @return 相應的變量值
? ? ?*/
? ? 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);


? ? /**
? ? ?* 根據field id為相應的變量設置新的值,field Id通過GetFieldID()獲取
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj java對象
? ? ?* @param fieldID 有效的field id
? ? ?* @param value 要設置的值
? ? ?*/
? ? 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);


? ? /**
? ? ?* 返回靜態方法的method ID
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param name 方法名
? ? ?* @param sig 方法簽名
? ? ?*
? ? ?* @return 方法ID or NULL
? ? ?*
? ? ?* @throws NoSuchMethodError 找不到對應的方法
? ? ?* @throws ExceptionInInitializerError class初始化失敗
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jmethodID (*GetStaticMethodID)(JNIEnv *, jclass, const char *, const char *);


? ? /**
? ? ?* CallStatic<type>Method(JNIEnv *env, jclass clazz, jmethodID methodID, ...);調用參數放到可變參數中
? ? ?* CallStatic<type>MethodA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);調用參數放入jvalue數組
? ? ?* CallStatic<type>MethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);調用參數放入va_list結構中
? ? ?*
? ? ?* 以上三組調用接口都是根據 method ID調用java靜態方法的接口,其中method ID是通過GetStaticMethodID()獲取的
? ? ?* method ID必須從clazz的真實類獲取,而不應從其某個父類獲取
? ? ?* <type>是方法的返回類型,三類接口間唯一的區別是methodID參數之后調用參數的不同
? ? ?*
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param methodID 方法ID
? ? ?* @param args 調用參數
? ? ?*
? ? ?* @return java方法返回結果
? ? ?*
? ? ?* @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 *);


? ? /**
? ? ?* 根據class對象獲取靜態成員變量的field ID
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param name 變量名
? ? ?* @param sig 變量簽名
? ? ?*
? ? ?* @return field ID or NULL
? ? ?*
? ? ?* @throws NoSuchFieldError 找不到對應的變量ID
? ? ?* @throws ExceptionInInitializerError class初始化失敗
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jfieldID (*GetStaticFieldID)(JNIEnv *, jclass, const char *, const char *);


? ? /**
? ? ?* 根據field id取出對象中相應的變量值,field Id通過GetStaticFieldID()獲取
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param fieldID 有效的field id
? ? ?*
? ? ?* @return 相應的靜態變量值
? ? ?*/
? ? 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);


? ? /**
? ? ?* 根據field id為相應的靜態變量設置新的值,field Id通過GetStaticFieldID()獲取
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param fieldID 有效的field id
? ? ?* @param value 要設置的值
? ? ?*/
? ? 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);


? ? /**
? ? ?* 創建一個新的java.lang.String對象
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param unicodeChars 指向Unicode字符串的指針
? ? ?* @param len Unicode字符串的長度
? ? ?*
? ? ?* @return String對象 or NULL
? ? ?*
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jstring (*NewString)(JNIEnv *, const jchar *, jsize);


? ? /**
? ? ?* 返回java.lang.String的長度(Unicode字符數)
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param string String對象
? ? ?*
? ? ?* @return 長度
? ? ?*/
? ? jsize (*GetStringLength)(JNIEnv *, jstring);


? ? /**
? ? ?* 返回指向Unicode字符數組的指針
? ? ?* 該指針在調用ReleaseStringchars()前一直有效
? ? ?* 如果isCopy非空,則在復制完成后將*isCopy設為JNI_TRUE。否則設為JNI_FALSE
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param string String對象
? ? ?* @param isCopy 指向boolean的指針
? ? ?*
? ? ?* @return 指向字符串的指針 or NULL
? ? ?*/
? ? const jchar *(*GetStringChars)(JNIEnv *, jstring, jboolean *);


? ? /**
? ? ?* 通知VM無需再訪問chars
? ? ?* chars是一個指針,通過GetStringChars()
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param string String對象
? ? ?* @param chars 指向字符串的指針
? ? ?*/
? ? void (*ReleaseStringChars)(JNIEnv *, jstring, const jchar *);


? ? /**
? ? ?* 根據UTF-8編碼的字符數組創建一個新的java.lang.String對象
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param bytes 指向UTF-8字符串的指針
? ? ?*
? ? ?* @return String對象 or NULL
? ? ?*
? ? ?* @throws OutOfMemoryError 內存不足
? ? ?*/
? ? jstring (*NewStringUTF)(JNIEnv *, const char *);


? ? /**
? ? ?* 返回字符串以UTF-8為編碼的字節數
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param string String對象
? ? ?*
? ? ?* @return 字符串的UTF-8字節數
? ? ?*/
? ? jsize (*GetStringUTFLength)(JNIEnv *, jstring);


? ? /**
? ? ?* 返回指向UTF-8編碼字符數組的指針
? ? ?* 該指針在調用ReleaseStringUTFChars()前一直有效
? ? ?* 如果isCopy非空,則在復制完成后將*isCopy設為JNI_TRUE。否則設為JNI_FALSE
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param string String對象
? ? ?* @param isCopy 指向boolean的指針
? ? ?*
? ? ?* @return 指向字符串的指針 or NULL
? ? ?*/
? ? const char *(*GetStringUTFChars)(JNIEnv *, jstring, jboolean *);


? ? /**
? ? ?* 通知VM無需再訪問utf
? ? ?* utf是一個指針,通過GetStringUTFChars()
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param string String對象
? ? ?* @param utf 指向字符串的指針
? ? ?*/
? ? void (*ReleaseStringUTFChars)(JNIEnv *, jstring, const char *);


? ? /**
? ? ?* 獲取數組元素個數
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param array java數組對象
? ? ?*
? ? ?* @return 數組長度
? ? ?*/
? ? jsize (*GetArrayLength)(JNIEnv *, jarray);


? ? /**
? ? ?* 創建新的elementClass類型數組,所有元素初始值均設為initialElement
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param length 數組大小
? ? ?* @param elementClass 數組類型
? ? ?* @param initialElement 初始值
? ? ?*
? ? ?* @return 數組對象 or NULL
? ? ?*/
? ? jobjectArray (*NewObjectArray)(JNIEnv *, jsize, jclass, jobject);


? ? /**
? ? ?* 獲取對象數組中指定index的值
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param array java數組
? ? ?* @param index 索引
? ? ?*
? ? ?* @return 索引對象的對象
? ? ?*
? ? ?* @throws ArrayIndexOutOfBoundsException
? ? ?*/
? ? jobject (*GetObjectArrayElement)(JNIEnv *, jobjectArray, jsize);


? ? /**
? ? ?* 設置對象數組中指定index的值
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param array java數組
? ? ?* @param index 索引
? ? ?* @param value 新的值
? ? ?*
? ? ?* @throws ArrayIndexOutOfBoundsException
? ? ?*/
? ? void (*SetObjectArrayElement)(JNIEnv *, jobjectArray, jsize, jobject);


? ? /**
? ? ?* ArrayType New<PrimitiveType>Array(JNIEnv *env, jsize length);
? ? ?* 創建基本類型數組對象
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param length 數組大小
? ? ?*
? ? ?* @return 數組對象 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);
? ? ?* 返回基本類型數組中的數據,通過返回的指針可以訪問這些數據,若虛擬機支持pinning,則指針指向原始數組,否則指向原始數組的拷貝
? ? ?* 返回的指針在Release<PrimitiveType>ArrayElements()調用前一直有效
? ? ?* 數組用使用結束后,調用Release<PrimitiveType>ArrayElements,并在調用參數中決定是否把修改提交給java
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param array java數組
? ? ?* @param isCopy 指向boolean的指針,若不為NULL,則執行了復制設為JNI_TRUE,否則設為JNI_FALSE
? ? ?*
? ? ?* @return 指向數組元素的指針 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不再需要訪問這些數組,根據mode參數的不同,將決定是否把數組的修改復制到源數組
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param array java數組對象
? ? ?* @param elems 指向數組元素的指針
? ? ?* @param mode 釋放模式,0:把數據復制回源數組并釋放elems緩沖區,JNI_COMMIT:把數據復制回源數組但不釋放elems緩沖區,JNI_ABORT:不把數據復制回源數組,釋放elems緩沖區
? ? ?*/
? ? 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);
? ? ?* 把基本類型數組拷貝到buf中
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param array java數組
? ? ?* @param start 開始index
? ? ?* @param len 拷貝長度
? ? ?* @param buf 目標地址
? ? ?*
? ? ?* @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中的內容拷貝回數組中
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param array java數組
? ? ?* @param start 開始index
? ? ?* @param len 拷貝長度
? ? ?* @param buf 源數據
? ? ?*
? ? ?* @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類注冊本地方法
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?* @param methods clazz類中的本地方法,指向方法數組
? ? ?* @param nMethods 本地方法個數
? ? ?*
? ? ?* @return 0:成功, 負數:失敗
? ? ?*
? ? ?* @throws NoSuchMethodError
? ? ?*/
? ? jint (*RegisterNatives)(JNIEnv *, jclass, const JNINativeMethod *, jint);


? ? /**
? ? ?* 取消clazz類本地方法的注冊
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param clazz class對象
? ? ?*
? ? ?* @return 0:成功, 負數:失敗
? ? ?*/
? ? jint (*UnregisterNatives)(JNIEnv *, jclass);


? ? /**
? ? ?* 進入與obj所引用的Java對象相關聯的監控,obj 必須為非空
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj java對象 或 class對象
? ? ?*
? ? ?* @return 0:成功, 負數:失敗
? ? ?*/
? ? jint (*MonitorEnter)(JNIEnv *, jobject);


? ? /**
? ? ?* 退出與obj所引用的Java對象相關聯的監控,obj 必須為非空
? ? ?* 當前線程必須是與obj所引用的Java對象相關聯的監控程序的所有者
? ? ?* 監控程序次數的計數器減 1。如果計數器的值變為 0,則釋放當前線程的監控程序
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj java對象 或 class對象
? ? ?*
? ? ?* @return 0:成功, 負數:失敗
? ? ?*/
? ? jint (*MonitorExit)(JNIEnv *, jobject);


? ? /**
? ? ?* 獲取當前線程關聯的Java VM接口
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param vm java VM接口指針
? ? ?*
? ? ?* @return 0:成功, 負數:失敗
? ? ?*/
? ? jint (*GetJavaVM)(JNIEnv *, JavaVM **);


? ? /**
? ? ?* 從start index開始,拷貝len個Unicode字符到buf
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param str string對象
? ? ?* @param start 開始index
? ? ?* @param len 拷貝長度
? ? ?* @param buf 目標地址
? ? ?*
? ? ?* @throws StringIndexOutOfBoundsException
? ? ?*/
? ? void (*GetStringRegion)(JNIEnv *, jstring, jsize, jsize, jchar *);


? ? /**
? ? ?* 從start index開始,取出len個Unicode字符轉換為UTF-8編碼后拷貝到buf
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param str string對象
? ? ?* @param start 開始index
? ? ?* @param len 拷貝長度
? ? ?* @param buf 目標地址
? ? ?*
? ? ?* @throws StringIndexOutOfBoundsException
? ? ?*/
? ? void (*GetStringUTFRegion)(JNIEnv *, jstring, jsize, jsize, char *);


? ? /**
? ? ?* 與Get/Release<primitivetype>ArrayElements方法非常相似,在這個方法中VM盡量返回指向原始數組的指針
? ? ?*
? ? ?* @since JDK/JRE 1.2
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param array java數組
? ? ?* @param isCopy 指向boolean的指針,若不為NULL,則執行了復制設為JNI_TRUE,否則設為JNI_FALSE
? ? ?*
? ? ?* @return 指向數組元素的指針 or NULL
? ? ?*/
? ? void *(*GetPrimitiveArrayCritical)(JNIEnv *, jarray, jboolean *);
? ? void (*ReleasePrimitiveArrayCritical)(JNIEnv *, jarray, void *, jint);


? ? /**
? ? ?* 與Get/ReleaseStringChars方法非常相似,在這個方法中VM盡量返回指向原始字符串的指針
? ? ?*
? ? ?* @since JDK/JRE 1.2
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param string String對象
? ? ?* @param isCopy 指向boolean的指針
? ? ?*
? ? ?* @return 指向字符串的指針 or NULL
? ? ?*/
? ? const jchar *(*GetStringCritical)(JNIEnv *, jstring, jboolean *);
? ? void (*ReleaseStringCritical)(JNIEnv *, jstring, const jchar *);


? ? /**
? ? ?* 為傳入的obj創建弱全局引用
? ? ?* 弱全局引用不會阻止VM釋放所引用的對象,程序中可以通過使用IsSameObject比較弱全局引用和NULL來確認所引用的對象是否被釋放
? ? ?*
? ? ?* @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 *);


? ? /**
? ? ?* 創建并返回java.nio.ByteBuffer對象,該對象引用以address為開始地址,大小為capacity的內存塊
? ? ?*
? ? ?* @since JDK/JRE 1.4
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param address 開始地址
? ? ?* @param capacity 內存大小
? ? ?*
? ? ?* @return Jjava.nio.ByteBuffer or NULL
? ? ?*
? ? ?* @throws OutOfMemoryError
? ? ?*/
? ? jobject (*NewDirectByteBuffer)(JNIEnv *, void *, jlong);


? ? /**
? ? ?* 根據java.nio.ByteBuffer對象,獲取相應的內存數據并返回開始地址
? ? ?*
? ? ?* @since JDK/JRE 1.4
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param buf java.nio.ByteBuffer對象
? ? ?*
? ? ?* @return 數據的開始地址 or NULL
? ? ?*/
? ? void *(*GetDirectBufferAddress)(JNIEnv *, jobject);


? ? /**
? ? ?* 根據java.nio.ByteBuffer對象,獲取相應的內存數據的大小
? ? ?*
? ? ?* @since JDK/JRE 1.4
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param buf java.nio.ByteBuffer對象
? ? ?*
? ? ?* @return 數據大小 or -1
? ? ?*/
? ? jlong (*GetDirectBufferCapacity)(JNIEnv *, jobject);


? ? /**
? ? ?* 獲取java對象的引用類型,可能的返回值有:
? ? ?* JNIInvalidRefType
? ? ?* JNILocalRefType:局部引用
? ? ?* JNIGlobalRefType:全局引用
? ? ?* JNIWeakGlobalRefType :全局弱若引用
? ? ?*
? ? ?* @since JDK/JRE 1.6
? ? ?*
? ? ?* @param env JNI接口指針
? ? ?* @param obj java對象的引用
? ? ?*
? ? ?* @return 引用類型
? ? ?*/
? ? jobjectRefType (*GetObjectRefType)(JNIEnv *, jobject);

?

總結

以上是生活随笔為你收集整理的JNI教程与技术手册的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

中文字幕资源网 国产 | 在线电影 一区 | 中文字幕亚洲综合久久五月天色无吗'' | 久久久国产精品久久久 | 久久高清免费视频 | 就要干b | 97偷拍视频 | 精品亚洲在线 | av电影中文字幕在线观看 | 免费av网址在线观看 | 水蜜桃亚洲一二三四在线 | 区一区二区三在线观看 | 国产又粗又猛又爽又黄的视频免费 | 999热线在线观看 | 欧美伦理一区二区 | 国产高清视频色在线www | 成人黄色电影在线播放 | 国产精品美女久久久久久久久 | 中文在线中文资源 | 天天拍天天操 | 国产在线久草 | 国产中文字幕网 | 麻豆影视网站 | 麻豆免费精品视频 | 99久久99久久精品国产片果冰 | 久久国产精品一区二区三区四区 | 中文av影院| 成年人免费看的视频 | 久久免费视频7 | 欧美精品一区二区免费 | 午夜a区| 免费黄色在线网址 | 欧洲激情综合 | 亚洲欧洲中文日韩久久av乱码 | 国产免费一区二区三区网站免费 | 国产免费作爱视频 | 国产专区在线播放 | 精品中文字幕在线观看 | 黄色毛片大全 | 2020天天干夜夜爽 | h视频在线看 | 久久不射电影院 | 亚洲精品乱码久久久久久蜜桃不爽 | 国产精品高清在线观看 | 国产小视频91| 五月婷婷视频在线观看 | 激情五月激情综合网 | 操少妇视频 | 操高跟美女| 欧美亚洲精品在线观看 | 美女一区网站 | 国产精品久久久久久久久久不蜜月 | 91高清一区 | 少妇bbr搡bbb搡bbb | 8x成人免费视频 | 亚洲1级片 | 久久视频免费观看 | 亚洲天堂精品 | 极品久久久| 久久精品毛片基地 | 成年人在线观看免费视频 | 99精品热视频只有精品10 | 亚洲美女视频网 | 国内精品免费久久影院 | 亚洲人天堂 | 国内丰满少妇猛烈精品播 | 在线蜜桃视频 | 久久精品毛片 | 美女久久精品 | 国产精品粉嫩 | 欧美久久久久久久 | 超碰97.com| 六月天色婷婷 | 国产网红在线观看 | 日韩a在线播放 | av高清在线观看 | 国内一级片在线观看 | 亚洲成人黄色网址 | 欧美日韩免费观看一区=区三区 | 精品91久久久久 | 中文字幕一区二区三区在线观看 | 久久男人中文字幕资源站 | 91最新在线 | 亚洲成人一二三 | 日韩一区二区三区免费视频 | 日韩资源视频 | 久久久久久久久久久久av | 久久久精品网站 | 黄色精品久久久 | 国产精品第一页在线 | 亚洲精品乱码久久 | 精品国精品自拍自在线 | 久久精品影片 | 二区精品视频 | 亚洲无吗av | 西西4444www大胆视频 | 在线不卡中文字幕播放 | 国产精品小视频网站 | 嫩草av影院| 日韩欧美高清视频在线观看 | 91尤物国产尤物福利在线播放 | 99视| 久久久久久久久久久久久国产精品 | 久久96国产精品久久99软件 | 天堂黄色片 | 热久精品 | 2023亚洲精品国偷拍自产在线 | 精品国产片 | 欧美日韩一区二区三区在线免费观看 | 亚洲精品男女 | 久久免费在线观看 | 国产亚洲人成网站在线观看 | 91人人人| 婷婷免费在线视频 | 国产原创av在线 | 成人在线一区二区 | 欧美精品黑人性xxxx | 青草草在线视频 | 国产黄色在线观看 | 国产日韩精品在线观看 | 亚洲视频1区2区 | 久久丁香网 | 一级一片免费观看 | 在线视频婷婷 | 六月色婷 | 久草在线资源观看 | 精品福利视频在线 | 精品99免费 | 欧美一二三视频 | 96久久精品 | 亚洲高清精品在线 | 国产精品视频久久 | 日韩视频免费在线观看 | 日韩精品一卡 | 人成午夜视频 | 亚洲视频一区二区三区在线观看 | 欧美日韩精品影院 | 一区二区影院 | 午夜久久影视 | 五月开心网 | 日本字幕网 | 98精品国产自产在线观看 | 91精品视频在线 | 亚洲国产97在线精品一区 | 欧美一二区视频 | 成人97人人超碰人人99 | 久久99国产精品二区护士 | 精品伊人久久久 | 人人干人人做 | 99久久精品费精品 | 成人av中文字幕在线观看 | 九九99靖品| 日韩在线第一 | 精品欧美在线视频 | 丁香激情综合 | 精品在线观看免费 | 青青河边草免费直播 | 亚洲成av人片在线观看www | 日韩免费高清在线 | 国产精品情侣视频 | 日韩精品久久久久久久电影竹菊 | 久久久久久国产精品 | 美女网站在线播放 | 九九九九九九精品任你躁 | www.亚洲激情.com | 91自拍91| 手机在线观看国产精品 | av福利网址导航大全 | 国产视频一区二区三区在线 | 国产精品一区二区久久国产 | 玖玖玖国产精品 | 久久久久久久久久久电影 | 日韩中文字幕在线观看 | 99热官网 | 狠狠色丁香婷婷综合久小说久 | 97在线视频网站 | 精品在线一区二区 | 国产黄色片一级 | 一区二区三区免费在线 | 天天操天天射天天操 | 欧美三级高清 | www.久久婷婷| 免费69视频 | 欧美精品久久久久久久久免 | 中文字幕在线观看av | 超碰在线人人草 | 天天操天天干天天操天天干 | 丁香激情婷婷 | 99久久9| 天天操夜夜逼 | 日韩免费看片 | 五月婷婷久久综合 | 成人免费xyz网站 | 婷婷深爱| 日韩高清不卡在线 | 亚洲国产wwwccc36天堂 | 日本中文一级片 | 久久精品99视频 | 久久影视一区二区 | 日日夜夜精品免费观看 | 国产色婷婷 | 黄色大全免费观看 | 91色视频 | 九九九热精品免费视频观看 | 五月婷婷色播 | 成人一区二区三区在线观看 | 一级一级一片免费 | 综合激情婷婷 | 国产手机av | 国产精品99久久久久久久久 | 国产中文字幕在线视频 | 国产伦理一区二区 | 黄色成人影院 | 69性欧美| 婷婷狠狠操 | a级黄色片视频 | 亚洲女在线| 日b视频国产 | 亚洲精品啊啊啊 | 久久久综合九色合综国产精品 | 97电影在线看视频 | 五月婷婷爱 | 中文字幕在线第一页 | 91精品婷婷国产综合久久蝌蚪 | 人人爽久久涩噜噜噜网站 | 日韩色中色 | 日韩精品一区二区三区在线播放 | 久久精品国产免费 | 国产免费叼嘿网站免费 | 亚洲区另类春色综合小说 | 久久国产精品久久精品国产演员表 | 国产中文字幕在线看 | 99产精品成人啪免费网站 | 免费成人在线视频网站 | 国产这里只有精品 | 婷婷色五 | 欧美最猛性xxxxx免费 | 最近2019好看的中文字幕免费 | 狠狠狠狠狠操 | 69国产盗摄一区二区三区五区 | 91大神在线观看视频 | 国产精品手机看片 | 国产精彩视频一区 | 狠狠色狠狠色综合日日小说 | 欧日韩在线 | 欧美日韩一区二区久久 | 久草网首页 | 欧美日韩免费网站 | 欧美性色黄 | 亚洲国产一区二区精品专区 | 丁香六月久久综合狠狠色 | 97人人爽人人 | 五月婷婷综合在线视频 | 久草.com| 久久99久国产精品黄毛片入口 | 国产成人av网址 | 亚洲蜜桃在线 | 免费精品在线观看 | 久久97精品| 水蜜桃亚洲一二三四在线 | 天天操天天舔天天爽 | 日韩在线视频观看免费 | 偷拍视频一区 | 国产免费专区 | 日韩成人在线一区二区 | 三级a毛片 | 午夜影院三级 | 亚洲性xxxx | 国语久久| 69成人在线 | 天天干,夜夜爽 | www天天操 | 毛片永久新网址首页 | 日韩av成人 | 国产91aaa| 免费av一级电影 | 久久人人爽人人片av | 日本一区二区三区免费看 | 国产自在线观看 | 99热最新 | 国产99久久久精品视频 | 黄色电影小说 | 久久一区91 | 毛片3| 成人久久18免费网站麻豆 | 91精品国产99久久久久久红楼 | 免费观看丰满少妇做爰 | 久久精品香蕉视频 | 亚洲激情 欧美激情 | 国产成人免费av电影 | 黄色亚洲大片免费在线观看 | 国产精品一区二区久久国产 | 一区二区三区韩国免费中文网站 | 2022中文字幕在线观看 | 欧美一区二区三区免费观看 | 欧美日韩国产一区 | 91毛片在线观看 | 成人av电影免费在线观看 | 韩国一区在线 | 免费久久99精品国产 | 亚洲va欧美va国产va黑人 | 天天干夜夜爱 | 激情av资源 | 国产成人av免费在线观看 | 狠狠狠狠干 | 91精品国产91久久久久福利 | 久久亚洲电影 | 欧美污网站 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 色婷婷av一区 | 日韩欧美一区二区三区视频 | 免费在线观看不卡av | 成全在线视频免费观看 | 欧美激情在线网站 | 久久都是精品 | 最新av在线免费观看 | 免费观看视频的网站 | 日韩黄在线观看 | 五月天高清欧美mv | 国产亚洲精品久久19p | 玖玖色在线观看 | 日韩一区二区三区不卡 | 久久精品视频播放 | 亚洲成色777777在线观看影院 | 国产精品理论片在线观看 | 国产免费成人av | a黄色片在线观看 | 久草视频在线播放 | 91探花在线 | 欧美日韩中文视频 | 国产中文视频 | 天天看天天操 | 免费一级毛毛片 | 成人欧美日韩国产 | 一区二区av | 中文字幕 成人 | 久久黄色片 | 丁香色综合 | 99tvdz@gmail.com| 国产男女爽爽爽免费视频 | 一二三久久久 | 91成人精品在线 | 久草在线免费资源站 | 人人爽久久久噜噜噜电影 | 日韩成人在线一区二区 | 国产亚洲aⅴaaaaaa毛片 | 亚洲天堂激情 | 国产原创在线 | 99tvdz@gmail.com| 911香蕉 | 亚洲欧美日韩国产一区二区三区 | 久久久久久久久综合 | 亚洲亚洲精品在线观看 | 亚洲激情在线 | 国产原创在线观看 | 免费观看一区二区三区视频 | 国产视频在线免费观看 | a视频在线看 | 久久久999免费视频 日韩网站在线 | 色播五月激情五月 | 在线观看日韩免费视频 | 欧美国产不卡 | 亚洲91精品| 中文字幕在线成人 | 中午字幕在线观看 | 久久国产影院 | 日日夜夜精品 | 91大神dom调教在线观看 | 天天色天天综合 | 99精品免费网 | 五月综合在线观看 | 欧美激情视频一二三区 | 亚洲最新视频在线播放 | 国产在线p | 国产精品99久久久久久宅男 | 国产免费观看久久黄 | 丁香花在线观看视频在线 | 99热这里精品 | 久久久久久毛片精品免费不卡 | 日韩久久精品一区二区 | 韩国一区二区三区视频 | 狠狠狠干 | .国产精品成人自产拍在线观看6 | 日韩欧美高清视频在线观看 | 成人全视频免费观看在线看 | 久久综合五月天 | 中文字幕九九 | 香蕉影院在线播放 | 91麻豆国产福利在线观看 | 91九色视频在线播放 | 欧美大片www | 在线看片一区 | 成人观看| 国产精品久久久久久久久久ktv | 色婷婷欧美| 国语精品久久 | 奇米网网址 | 国产久草在线 | 国产色网站 | 国产一级片在线播放 | 色婷婷久久久综合中文字幕 | 久久小视频 | 999久久a精品合区久久久 | 欧美一级日韩免费不卡 | 欧美成年网站 | 国产精品观看视频 | 亚洲视频专区在线 | 国产成人精品午夜在线播放 | 国产中文字幕在线免费观看 | 天天射天天爱天天干 | 日韩特级黄色片 | 成人免费视频网站在线观看 | 日韩av电影中文字幕 | 日韩av偷拍 | 四虎在线免费观看 | 操操操日日 | 色欧美日韩 | 国产婷婷一区二区 | 99精品视频免费在线观看 | aⅴ精品av导航 | 99精品国产免费久久久久久下载 | 2000xxx影视| 日韩在线观看精品 | 国产一区久久久 | 中文字幕 在线看 | 亚洲国产精品电影 | 999视频在线播放 | 97国产精品 | 精品播放| 日日日日日 | 人人爽人人爽人人片av | 久久免费看a级毛毛片 | 99热99热| 欧美日韩国产综合一区二区 | 国产精品黑丝在线观看 | 欧美性生活小视频 | 九九日韩 | 日本韩国在线不卡 | 国产免费精彩视频 | 亚洲精品乱码白浆高清久久久久久 | 免费看的黄色片 | 色国产精品一区在线观看 | 日本久久不卡视频 | 欧美性极品xxxx做受 | 欧美午夜精品久久久久久孕妇 | 人人澡人人澡人人 | 日韩av免费一区 | 成人在线中文字幕 | 中文字幕av电影下载 | 久久这里只有精品视频首页 | 日韩av免费一区 | 精品视频免费久久久看 | 人人澡澡人人 | 国产在线观看国语版免费 | 日韩av免费在线电影 | 久久人人爽人人 | 中文字幕日韩精品有码视频 | 亚洲精品国产日韩 | 久久91网 | 亚洲精品1234区 | 精品国产一区二区三区久久久 | 天天干天天在线 | 国产成人99av超碰超爽 | 午夜久久影视 | 精品国产乱码久久久久久1区二区 | 五月激情姐姐 | 亚洲精品国产综合99久久夜夜嗨 | 国产专区日韩专区 | 久久99在线观看 | 日韩免费一二三区 | 久久精品二区 | 黄色网址av| 亚洲精品国产精品国自产观看浪潮 | 91自拍视频在线观看 | 天天做日日爱夜夜爽 | 日韩欧美高清在线 | 国产午夜三级一区二区三桃花影视 | 国产中文在线视频 | 国产白浆在线观看 | 国产精品亚洲精品 | 国产精品成人a免费观看 | 国产精品成人a免费观看 | 丁香在线视频 | 天天搞天天 | 五月婷婷久草 | 国产精品色| 久草免费手机视频 | 99久久精品国产观看 | 欧美激情h| 尤物97国产精品久久精品国产 | 久久精品一区二区国产 | 91在线中字| 一区二区不卡在线观看 | 成人午夜黄色 | 欧美国产日韩在线观看 | www久久 | 在线黄色国产电影 | 欧美成年人在线视频 | 国产在线观看99 | 亚洲成人蜜桃 | 99久久婷婷国产综合亚洲 | 在线免费观看视频a | 久久久国产精品一区二区中文 | 激情五月婷婷综合网 | 一区二区三区在线视频111 | 久久五月婷婷丁香 | www夜夜操 | 97热久久免费频精品99 | 在线视频 国产 日韩 | 91在线一区 | 精壮的侍卫呻吟h | 久久99国产精品视频 | 手机成人在线 | 免费看久久 | 成人黄色电影在线播放 | 深夜免费网站 | 中文在线字幕免费观 | 91香蕉视频720p| 日韩免费中文字幕 | 日本三级久久 | 国产一区二区在线免费观看 | 欧美日韩不卡一区二区三区 | 开心激情综合网 | 精品国产一区二区三区噜噜噜 | 国产精品久久久久久久久久久杏吧 | 看av免费网站 | 日韩av一区在线观看 | 成人影视片 | 99 色| 草草草影院 | 成人h在线 | 99久久精品午夜一区二区小说 | 久久成人免费电影 | 日韩videos高潮hd | 在线看不卡av | 91精品久久久久久综合乱菊 | 国产精品女教师 | 91精品啪在线观看国产线免费 | 国产在线小视频 | 久久综合桃花 | 操操操操网 | 国产一级片久久 | 亚洲国产成人精品久久 | 欧美日韩裸体免费视频 | 在线va网站 | 深爱婷婷激情 | 久久久视频在线 | 国产主播99 | 亚洲综合在线播放 | 国产午夜精品一区二区三区四区 | 一区二区三区日韩在线观看 | 欧美粗又大 | 丁香激情综合久久伊人久久 | 五月婷婷六月丁香激情 | 国产精品成人a免费观看 | 99久久婷婷国产精品综合 | 欧美一级性生活视频 | 国产精品欧美久久久久天天影视 | 粉嫩av一区二区三区四区五区 | 国产精品免费大片视频 | 亚洲国产精品va在线看黑人 | 超碰97免费在线 | 色婷婷88av视频一二三区 | 99精品视频网 | 六月色丁香 | 国产美女精品久久久 | 中中文字幕av| 九九九九免费视频 | 人人插人人做 | 久久久高清一区二区三区 | 日韩一级成人av | 在线av资源 | 玖玖精品视频 | 精品日韩中文字幕 | 91激情在线视频 | 六月丁香激情网 | 日日操夜夜操狠狠操 | 九九九热精品 | 91人人干 | av再线观看 | 成人在线中文字幕 | 婷婷久久精品 | 四虎最新域名 | 韩日电影在线 | 日韩一区正在播放 | 日韩成人中文字幕 | 欧美日韩在线视频免费 | 波多野结衣电影一区二区三区 | 在线欧美日韩 | 天天色天天草天天射 | 久久社区视频 | 久久精品久久99精品久久 | 国产精品久久电影网 | 2024国产精品视频 | 亚洲欧美日韩不卡 | 国产精品毛片久久久久久久 | 欧美在线视频第一页 | 亚洲影视九九影院在线观看 | 欧美视频www | 国产亚洲免费的视频看 | av三级在线免费观看 | 27xxoo无遮挡动态视频 | 黄色亚洲精品 | 四虎在线观看视频 | 青草视频在线 | 久久精品免视看 | 久久毛片网站 | 亚洲精品大片www | 欧美福利网站 | 最新真实国产在线视频 | 婷婷av在线 | 91av视频在线观看 | 日韩在线网| 国产最新91| 日韩精品中文字幕久久臀 | 国产精品6999成人免费视频 | 婷婷国产在线 | 国产精品久久精品 | 三级在线视频播放 | 久久99热精品这里久久精品 | 色999在线| 成人四虎| 日韩av免费在线电影 | 美女视频a美女大全免费下载蜜臀 | 欧美日韩免费一区二区三区 | 怡红院久久 | 伊人狠狠色丁香婷婷综合 | 黄色免费大片 | 在线观看免费版高清版 | www.婷婷色 | 国产精品观看在线亚洲人成网 | 国产亚洲精品久久久久久无几年桃 | 91精品久久久久 | 97在线视频免费看 | 成人免费看视频 | 992tv人人网tv亚洲精品 | 欧美成人中文字幕 | 中文字幕乱视频 | 韩国一区二区三区在线观看 | 成人午夜影院在线观看 | 亚洲国产一区二区精品专区 | 99福利片 | 色中射 | 美女黄濒 | 深爱激情五月网 | 国产精品原创av片国产免费 | 国产一区二区在线播放视频 | 在线电影日韩 | 人人草在线观看 | 人人射人人澡 | www.黄色小说.com | 免费一级特黄录像 | 日韩久久久久久久久久久久 | 黄色a一级片 | 久久黄色a级片 | 亚洲在线国产 | 欧洲视频一区 | bbbbb女女女女女bbbbb国产 | 国产成人精品一区在线 | 日韩中文在线电影 | 久久久www成人免费精品 | 中文字幕av播放 | av在线观 | 西西www4444大胆在线 | 日韩免费在线视频观看 | 国产一级二级av | 国产一区二区不卡视频 | 成年人黄色av | 九九国产精品视频 | 国产r级在线观看 | 网址你懂的在线观看 | 国产精品久久久久久久午夜片 | 成 人 黄 色 视频 免费观看 | 日韩欧美亚洲 | 97人人添人澡人人爽超碰动图 | 中文字幕在线观看1 | 奇米影视777影音先锋 | 黄色a一级视频 | 欧美美女激情18p | 在线观看视频免费大全 | 欧美精品首页 | 国产精品久久久久久久久久三级 | 亚洲成人家庭影院 | 婷婷色网视频在线播放 | 欧美精品亚洲精品 | 日韩欧美综合在线视频 | 色综合久久中文综合久久牛 | 免费能看的av | 超碰在线98 | 精品久久久久久久久久久久久 | 久草网视频 | 五月天狠狠操 | 九九视频网站 | 99性视频| 91在线看免费 | 亚洲高清网站 | 私人av| 日韩免费三级 | 天天操天天添天天吹 | 亚洲最新视频在线 | 亚洲丁香久久久 | 黄色精品久久久 | 91精品国产乱码 | 色综合亚洲精品激情狠狠 | 激情av五月婷婷 | 日韩黄色免费电影 | 天天操夜夜操夜夜操 | 国产精品久久久久永久免费观看 | 国产老妇av | 探花视频免费观看高清视频 | 国产精品久久99 | 2022中文字幕在线观看 | 精品亚洲男同gayvideo网站 | 精品一区 精品二区 | 国产美女永久免费 | 亚洲激情视频 | 久久99国产精品免费 | 成人黄色av免费在线观看 | 成人国产一区二区 | 免费在线| 欧美一二三区在线观看 | 精品久久久久久久久久岛国gif | 美女免费视频网站 | 97超碰色 | 国产精品99久久99久久久二8 | av电影免费 | 中文电影网 | 在线观看mv的中文字幕网站 | 性色av一区二区 | 亚洲激情在线观看 | 国产精品久久一区二区三区不卡 | 久草免费在线视频观看 | 天天色中文 | 99久视频| 91手机视频在线 | 亚洲三级av| 天天·日日日干 | 日韩成人免费电影 | 日韩精品最新在线观看 | 蜜桃视频在线视频 | 欧美日韩性视频 | 国产精品白虎 | 亚洲高清不卡av | 国产成人精品一区二区 | 亚洲精品99久久久久久 | 久久激情视频 久久 | 偷拍久久久| 色吊丝av中文字幕 | 成人激情开心网 | 中文字幕av最新 | 毛片一级免费一级 | 国产二区电影 | 特级黄录像视频 | 亚洲伊人婷婷 | 亚洲作爱视频 | 日日干日日操 | 99精品视频在线观看免费 | 成人免费视频播放 | www.国产毛片 | 97国产精品亚洲精品 | 国产精品女同一区二区三区久久夜 | 国产一级在线免费观看 | 免费观看www小视频的软件 | 在线观看国产麻豆 | 中文字幕乱码亚洲精品一区 | 久久人网 | 一区二区三区免费网站 | 亚洲爱爱视频 | 国产精品久久99综合免费观看尤物 | 韩国av免费在线 | 日韩在线观看网站 | 国产精品视频不卡 | 成人免费中文字幕 | 国产精品无av码在线观看 | 亚洲精品99久久久久久 | av网站有哪些 | 日本精品视频在线 | av大片免费 | 日韩一区二区三区观看 | 激情视频一区二区三区 | 五月丁婷婷 | 亚洲 欧美 另类人妖 | 国产精品国产三级国产专区53 | 日韩av免费一区二区 | 狠狠干狠狠久久 | 久久精品网站免费观看 | 精品一二三区视频 | 国产不卡在线看 | 香蕉日日| 久久久久免费精品视频 | 久久国际影院 | 毛片视频电影 | 亚洲一级片免费观看 | 国产精品1区2区在线观看 | 精品99视频 | 久久亚洲综合国产精品99麻豆的功能介绍 | 亚州性色 | 国产日韩视频在线 | 激情综合五月天 | 国产精品视频观看 | 九九有精品 | 手机成人在线 | 国产99久久久国产精品 | av在线播放亚洲 | 女人18毛片90分钟 | 午夜丁香视频在线观看 | 久久久久久久久影视 | 奇米网在线观看 | 亚洲高清免费在线 | 西西444www大胆高清视频 | 丝袜少妇在线 | 国产精品一区二区久久 | 色网站视频 | 女人18精品一区二区三区 | 狠狠色噜噜狠狠狠狠2022 | 欧美精品少妇xxxxx喷水 | 久草在线资源观看 | 一区二区三区免费在线观看 | 国产精品亚 | 五月天综合网站 | 黄色h在线观看 | 一级精品视频在线观看宜春院 | 亚洲特级片 | 欧美日一级片 | 97理论电影 | 免费看搞黄视频网站 | 中中文字幕av | 国产精品专区在线观看 | 日韩在线视频二区 | 激情片av| 超级碰碰碰免费视频 | 国产成人91 | 中文亚洲欧美日韩 | 永久免费在线 | 婷婷国产一区二区三区 | 91一区啪爱嗯打偷拍欧美 | 特级毛片在线免费观看 | 91欧美视频网站 | 久久激情小说 | 国产成人精品日本亚洲999 | 最近最新中文字幕视频 | 99国产在线 | 亚洲一区久久久 | 91av视频在线观看 | 亚洲三级av | 日韩中文久久 | 99精品欧美一区二区三区 | 成人欧美一区二区三区在线观看 | 日韩午夜小视频 | 欧美福利精品 | 九九久久久久久久久激情 | 久久久色| 国产精品久久影院 | 超级碰碰视频 | 99精品视频在线观看播放 | 亚洲国产精品99久久久久久久久 | 中文字幕精品三级久久久 | 国产伦理一区 | 天天操天天射天天插 | 青草视频免费观看 | 欧美极品在线播放 | 久久久久激情 | 91在线91 | 久久噜噜少妇网站 | 欧美日韩视频在线观看一区二区 | 成人欧美一区二区三区在线观看 | 国产精品福利无圣光在线一区 | 欧美在线一二 | 四虎永久免费 | 色综合久久久久久中文网 | 香蕉视频久久 | 色综合久久久久综合 | free. 性欧美.com| 在线精品视频免费观看 | 久久天天综合网 | 五月天视频网站 | 青青河边草免费直播 | 精品一区二区三区香蕉蜜桃 | av高清一区| 国产一级在线免费观看 | 日本在线观看一区二区 | 三级av片 | 亚洲一区二区视频在线播放 | 中文字幕在线视频一区 | 国产一区二区高清 | 欧美精品少妇xxxxx喷水 | 免费在线国产视频 | 香蕉免费在线 | 激情在线网站 | 国产vs久久 | 国产馆在线播放 | 欧美日韩国产精品一区二区三区 | 91av视频在线免费观看 | 色婷婷欧美 | 99视频免费在线观看 | 日韩精品久久中文字幕 | 久久伊人精品天天 | 国产一区二区三区四区在线 | 精品国偷自产国产一区 | 成年人看片 | 亚洲永久精品国产 | 亚洲激情在线观看 | 人人揉人人揉人人揉人人揉97 | 这里只有精彩视频 | 精品国产综合区久久久久久 | 香蕉视频在线免费 | 亚洲天天在线日亚洲洲精 | av免费网| 中文字幕综合在线 | 免费看的黄色网 | sesese图片| 成人黄色在线观看视频 | 黄色av成人在线观看 | 免费看国产a | 欧美一区二区三区免费看 | 九九日韩| 国产日本在线 | 久久人人爽人人 | 中文字幕视频在线播放 | 欧美日韩一区久久 | 国产a精品 | 日本中文字幕在线 | 激情婷婷网 | 天天玩天天干天天操 | 久久婷婷一区二区三区 | 亚洲春色综合另类校园电影 | 香蕉在线视频播放网站 | 国产91成人| 九九免费精品 | 91最新国产 | 国产九九九九九 | 激情久久网| 天天操夜操 | 国产成人99av超碰超爽 | 久久这里| 亚洲激情小视频 | 国产成人精品久久久久 | 国产专区在线看 | 亚洲黄色高清 | 婷婷色网视频在线播放 | 久久精品欧美 | 中文字幕在线免费观看 | 欧美a在线看 | 五月天亚洲婷婷 | 日韩高清国产精品 | 亚洲日韩中文字幕 | 激情五月婷婷综合网 | a天堂中文在线 | 日本不卡123 | 婷婷日日 | 免费人做人爱www的视 | 97超碰精品| 午夜神马福利 | 国产精品一区二区三区久久 | 久久视频一区 | 亚洲狠狠婷婷 | 国产精品一区二区美女视频免费看 | 国产精品毛片完整版 | 91精品1区2区| 丁香婷婷社区 | 深爱婷婷 | 啪啪免费视频网站 | 午夜av大片 | 中日韩欧美精彩视频 | 亚洲欧美国产日韩在线观看 | 一级理论片在线观看 | 成人欧美一区二区三区在线观看 | 99久久精品免费看国产免费软件 | 久久精品欧美日韩精品 | 日韩有码在线播放 | 欧美三级高清 | 日韩av资源站 | av不卡免费看 | 在线观av| 精品天堂av | 激情av资源 | 国产麻豆精品一区 | 久久网站最新地址 | 欧美一级裸体视频 | 丁香九月激情 | 亚洲美女视频网 | 高清不卡毛片 | va视频在线观看 | 亚洲另类视频 | 国产精品美女免费视频 | 国产中文在线视频 | 黄色三级免费网址 | 四虎影视www | www国产一区 | 日日碰狠狠添天天爽超碰97久久 | 色视频在线 | 国产一区二区在线观看免费 | 在线亚洲高清视频 | 99精品色 | zzijzzij亚洲日本少妇熟睡 | 人人草人人草 | 免费av福利 | 中文字幕在线播放一区 |