源地址:http://blog.csdn.net/ztp800201/article/details/7351754
typedef const struct JNINativeInterface *JNIEnv;
const struct JNINativeInterface ... = {
NULL,
NULL,
NULL,
NULL,
GetVersion, //获取JNI版本号
DefineClass, //通过指定ClassLoader对象加载类
FindClass, //获取指定的Class类对象
FromReflectedMethod, //通过指定的java.lang.reflect.Method对象获取方法ID
FromReflectedField, //通过指定的java.lang.reflect.Field对象获取字段ID
ToReflectedMethod, //通过指定的方法ID获取java.lang.reflect.Method对象
GetSuperclass, //获取指定类的父类
IsAssignableFrom, //判断指定类是否继承自某类或实现了某个接口
ToReflectedField, //通过指定的字段ID获取java.lang.reflect.Field对象
Throw, //抛出指定的Throwable对象
ThrowNew, //抛出指定的Throwable对象,并制定消息
ExceptionOccurred, //获取未被清空或捕获的异常
ExceptionDescribe, //同printStackTrace()
ExceptionClear, //清除已被抛出的异常
FatalError, //抛出致命错误
PushLocalFrame, //Push/PopLocalFrame函数提供了本地引用管理的简便方法,在该函数对之间的代码段,所有创建的显式本地引用无需手动调用DeleteLocalReference函数释放,PopLocalFrame函数会自动释放这些本地引用
PopLocalFrame,
NewGlobalRef, //创建全局引用,必须被显式清除
DeleteGlobalRef, //清除全局引用
DeleteLocalRef, //清除本地引用,通常本地引用在原生代码返回时会自动清除,但是对于大数据,比如在循环中频繁创建Java对象,而该对象的只在一次循环中有效,这种情况下有必要显式调用DeleteLocalRef以通知VM尽快释放该对象。
IsSameObject, //判断是否为同一对象,可通过该方法判断弱引用是否已被释放(NULL)
NewLocalRef, //创建本地引用
EnsureLocalCapacity, //确保当前线程可以创建指定数量的本地引用
AllocObject, //创建一个新的对象,只分配内存,不调用任何构造方法(cdwang:应该是为了方便通过CallNonvirtual<Type>Method方法调用父类的构造函数初始化对象)
NewObject, //通过指定的构造函数创建对象,变长参数形式
NewObjectV, //同上,va_list形式
NewObjectA, //同上,数组形式
GetObjectClass, //获取对象的Class类对象
IsInstanceOf, //同instanceOf
GetMethodID, //获取实例(非静态)方法的ID
CallObjectMethod, //调用实例方法,object表示返回值类型
CallObjectMethodV,
CallObjectMethodA,
CallBooleanMethod,
CallBooleanMethodV,
CallBooleanMethodA,
CallByteMethod,
CallByteMethodV,
CallByteMethodA,
CallCharMethod,
CallCharMethodV,
CallCharMethodA,
CallShortMethod,
CallShortMethodV,
CallShortMethodA,
CallIntMethod,
CallIntMethodV,
CallIntMethodA,
CallLongMethod,
CallLongMethodV,
CallLongMethodA,
CallFloatMethod,
CallFloatMethodV,
CallFloatMethodA,
CallDoubleMethod,
CallDoubleMethodV,
CallDoubleMethodA,
CallVoidMethod,
CallVoidMethodV,
CallVoidMethodA,
CallNonvirtualObjectMethod, //调用非虚实例方法,通过class对象指定调用哪个类的非虚函数(cdwang:应该是某对象不调用自己的构造类的方法实现,而是调用父类的方法实现,这个方法节省了子类对象向父类对象的强制转换)
CallNonvirtualObjectMethodV,
CallNonvirtualObjectMethodA,
CallNonvirtualBooleanMethod,
CallNonvirtualBooleanMethodV,
CallNonvirtualBooleanMethodA,
CallNonvirtualByteMethod,
CallNonvirtualByteMethodV,
CallNonvirtualByteMethodA,
CallNonvirtualCharMethod,
CallNonvirtualCharMethodV,
CallNonvirtualCharMethodA,
CallNonvirtualShortMethod,
CallNonvirtualShortMethodV,
CallNonvirtualShortMethodA,
CallNonvirtualIntMethod,
CallNonvirtualIntMethodV,
CallNonvirtualIntMethodA,
CallNonvirtualLongMethod,
CallNonvirtualLongMethodV,
CallNonvirtualLongMethodA,
CallNonvirtualFloatMethod,
CallNonvirtualFloatMethodV,
CallNonvirtualFloatMethodA,
CallNonvirtualDoubleMethod,
CallNonvirtualDoubleMethodV,
CallNonvirtualDoubleMethodA,
CallNonvirtualVoidMethod,
CallNonvirtualVoidMethodV,
CallNonvirtualVoidMethodA,
GetFieldID, //获取成员字段ID
GetObjectField, //获取字段值
GetBooleanField,
GetByteField,
GetCharField,
GetShortField,
GetIntField,
GetLongField,
GetFloatField,
GetDoubleField,
SetObjectField, //设置字段值
SetBooleanField,
SetByteField,
SetCharField,
SetShortField,
SetIntField,
SetLongField,
SetFloatField,
SetDoubleField,
GetStaticMethodID, //获取静态方法ID
CallStaticObjectMethod, //调用静态方法
CallStaticObjectMethodV,
CallStaticObjectMethodA,
CallStaticBooleanMethod,
CallStaticBooleanMethodV,
CallStaticBooleanMethodA,
CallStaticByteMethod,
CallStaticByteMethodV,
CallStaticByteMethodA,
CallStaticCharMethod,
CallStaticCharMethodV,
CallStaticCharMethodA,
CallStaticShortMethod,
CallStaticShortMethodV,
CallStaticShortMethodA,
CallStaticIntMethod,
CallStaticIntMethodV,
CallStaticIntMethodA,
CallStaticLongMethod,
CallStaticLongMethodV,
CallStaticLongMethodA,
CallStaticFloatMethod,
CallStaticFloatMethodV,
CallStaticFloatMethodA,
CallStaticDoubleMethod,
CallStaticDoubleMethodV,
CallStaticDoubleMethodA,
CallStaticVoidMethod,
CallStaticVoidMethodV,
CallStaticVoidMethodA,
GetStaticFieldID, //获取静态字段ID
GetStaticObjectField, //获取字段值
GetStaticBooleanField,
GetStaticByteField,
GetStaticCharField,
GetStaticShortField,
GetStaticIntField,
GetStaticLongField,
GetStaticFloatField,
GetStaticDoubleField,
SetStaticObjectField, //设置字段值
SetStaticBooleanField,
SetStaticByteField,
SetStaticCharField,
SetStaticShortField,
SetStaticIntField,
SetStaticLongField,
SetStaticFloatField,
SetStaticDoubleField,
NewString, //通过指定Unicode格式字符数组构造Java String
GetStringLength, //获取Unicode字符的长度
GetStringChars, //获取字符数组
ReleaseStringChars, //通知VM可以释放String和由GetStringChars获取的字符数组
NewStringUTF, //通过指定UTF-8格式字符数组构造Java String
GetStringUTFLength,
GetStringUTFChars,
ReleaseStringUTFChars,
GetArrayLength, //获取数组长度
NewObjectArray, //通过指定的Class类对象和初始元素初始化一个Java对象数组
GetObjectArrayElement, //获取指定索引的对象元素
SetObjectArrayElement, //设置指定索引的对象元素
NewBooleanArray, //构造基本类型的Java数组
NewByteArray,
NewCharArray,
NewShortArray,
NewIntArray,
NewLongArray,
NewFloatArray,
NewDoubleArray,
GetBooleanArrayElements, //获取基本类型元素的C数组
GetByteArrayElements,
GetCharArrayElements,
GetShortArrayElements,
GetIntArrayElements,
GetLongArrayElements,
GetFloatArrayElements,
GetDoubleArrayElements,
ReleaseBooleanArrayElements, //通知VM可以释放Java数组和由前述方法族获取的C数组
ReleaseByteArrayElements,
ReleaseCharArrayElements,
ReleaseShortArrayElements,
ReleaseIntArrayElements,
ReleaseLongArrayElements,
ReleaseFloatArrayElements,
ReleaseDoubleArrayElements,
GetBooleanArrayRegion, //获取子数组
GetByteArrayRegion,
GetCharArrayRegion,
GetShortArrayRegion,
GetIntArrayRegion,
GetLongArrayRegion,
GetFloatArrayRegion,
GetDoubleArrayRegion,
SetBooleanArrayRegion, //设置子数组
SetByteArrayRegion,
SetCharArrayRegion,
SetShortArrayRegion,
SetIntArrayRegion,
SetLongArrayRegion,
SetFloatArrayRegion,
SetDoubleArrayRegion,
RegisterNatives, //映射原生代码
UnregisterNatives,
MonitorEnter,
MonitorExit,
GetJavaVM, //获取当前线程关联的VM
GetStringRegion, //获取子串
GetStringUTFRegion,
GetPrimitiveArrayCritical,
ReleasePrimitiveArrayCritical,
GetStringCritical, // Get/ReleaseStringCritical必须成对出现,语义和Get/ReleaseStringChars一样,但代码段中不能阻塞当前线程,也不能调用任何其他的JNI函数
ReleaseStringCritical,
NewWeakGlobalRef,
DeleteWeakGlobalRef,
ExceptionCheck, //判断是否有挂起的异常
NewDirectByteBuffer,
GetDirectBufferAddress,
GetDirectBufferCapacity
};
版本信息
GetVersion
jint GetVersion(JNIEnv *env);
参数
env:JNI 接口指针。
返回值:
高 16 位返回主版本号,低 16 位返回次版本号。
在 JDK1.1 中,GetVersion()
返回 0x00010001。
类操作
DefineClass
jclass DefineClass(JNIEnv *env, jobject loader,
const jbyte *buf, jsize bufLen);
参数:
env:JNI 接口指针。
返回值:
返回 Java 类对象。如果出错则返回NULL
。
抛出:
ClassFormatError:如果类数据指定的类无效。
ClassCircularityError
:如果类或接口是自身的超类或超接口。
FindClass
jclass FindClass(JNIEnv *env, const char *name);
该函数用于加载本地定义的类。它将搜索由CLASSPATH
环境变量为具有指定名称的类所指定的目录和 zip 文件。
参数:
env:JNI 接口指针。
name
:类全名(即包名后跟类名,之间由“/
”分隔)。如果该名称以“[
”(数组签名字符)打头,则返回一个数组类。
返回值:
返回类对象全名。如果找不到该类,则返回 NULL
。
抛出:
ClassFormatError:如果类数据指定的类无效。
ClassCircularityError
:如果类或接口是自身的超类或超接口。
NoClassDefFoundError
:如果找不到所请求的类或接口的定义。
GetSuperclass
jclass GetSuperclass(JNIEnv *env, jclass clazz);
如果 clazz
代表类而非类 object
,则该函数返回由 clazz
所指定的类的超类。
如果 clazz
指定类 object
或代表某个接口,则该函数返回NULL
。
参数:
env:JNI 接口指针。
返回值:
由 clazz
所代表的类的超类或 NULL
。
IsAssignableFrom
jboolean IsAssignableFrom(JNIEnv *env, jclass clazz1,
jclass clazz2);
确定 clazz1
的对象是否可安全地强制转换为clazz2
。
参数:
env:JNI 接口指针。
返回值:
下列某个情况为真时返回 JNI_TRUE
:
异常
Throw
jintThrow(JNIEnv *env, jthrowable obj);
参数:
env:JNI 接口指针。
返回值:
成功时返回 0,失败时返回负数。
抛出:
java.lang.Throwable
对象 obj
。
ThrowNew
jint ThrowNew(JNIEnv *env, jclass clazz,
const char *message);
利用指定类的消息(由 message
指定)构造异常对象并抛出该异常。
参数:
env:JNI 接口指针。
clazz
:java.lang.Throwable
的子类。
message
:用于构造java.lang.Throwable
对象的消息。
返回值:
成功时返回 0,失败时返回负数。
抛出:
新构造的 java.lang.Throwable
对象。
ExceptionOccurred
jthrowable ExceptionOccurred(JNIEnv *env);
确定是否某个异常正被抛出。在平台相关代码调用 ExceptionClear()
或 Java 代码处理该异常前,异常将始终保持抛出状态。
参数:
env:JNI 接口指针。
返回值:
返回正被抛出的异常对象,如果当前无异常被抛出,则返回NULL
。
ExceptionDescribe
void ExceptionDescribe(JNIEnv *env);
将异常及堆栈的回溯输出到系统错误报告信道(例如 stderr
)。该例程可便利调试操作。
参数:
env:JNI 接口指针。
ExceptionClear
void ExceptionClear(JNIEnv *env);
清除当前抛出的任何异常。如果当前无异常,则此例程不产生任何效果。
参数:
env:JNI 接口指针。
FatalError
void FatalError(JNIEnv *env, const char *msg);
参数:
env:JNI 接口指针。
全局及局部引用
NewGlobalRef
jobject NewGlobalRef(JNIEnv *env, jobject obj);
创建 obj
参数所引用对象的新全局引用。obj
参数既可以是全局引用,也可以是局部引用。全局引用通过调用 DeleteGlobalRef()
来显式撤消。
参数:
env:JNI 接口指针。
返回值:
返回全局引用。如果系统内存不足则返回 NULL
。
DeleteGlobalRef
void DeleteGlobalRef(JNIEnv *env, jobject globalRef);
参数:
env:JNI 接口指针。
DeleteLocalRef
void DeleteLocalRef(JNIEnv *env, jobject localRef);
删除 localRef
所指向的局部引用。
参数:
env:JNI 接口指针。
对象操作
AllocObject
jobject AllocObject(JNIEnv *env, jclass clazz);
分配新 Java 对象而不调用该对象的任何构造函数。返回该对象的引用。
参数:
env:JNI 接口指针。
返回值:
返回 Java 对象。如果无法构造该对象,则返回NULL
。
抛出:
InstantiationException:如果该类为一个接口或抽象类。
NewObject
NewObjectA
NewObjectV
jobject NewObject(JNIEnv *env, jclass clazz,
jmethodID methodID, ...);
jobject NewObjectA(JNIEnv *env,jclass clazz,
jmethodID methodID, jvalue *args);
jobject NewObjectV(JNIEnv *env,jclass clazz,
jmethodID methodID, va_list args);
构造新 Java 对象。方法 ID指示应调用的构造函数方法。该 ID 必须通过调用 GetMethodID()
获得,且调用时的方法名必须为 <init>
,而返回类型必须为 void
(V
)。
NewObject
编程人员应将传递给构造函数的所有参数紧跟着放在 methodID
参数的后面。NewObject()
收到这些参数后,将把它们传给编程人员所要调用的 Java 方法。
NewObjectA
编程人员应将传递给构造函数的所有参数放在 jvalues
类型的数组 args
中,该数组紧跟着放在 methodID
参数的后面。NewObject()
收到数组中的这些参数后,将把它们传给编程人员所要调用的 Java 方法。
NewObjectV
编程人员应将传递给构造函数的所有参数放在 va_list
类型的参数 args
中,该参数紧跟着放在 methodID
参数的后面。NewObject()
收到这些参数后,将把它们传给编程人员所要调用的 Java 方法。
参数:
env:JNI 接口指针。
NewObject 的其它参数:
传给构造函数的参数。
NewObjectA 的其它参数:
args:传给构造函数的参数数组。
NewObjectV 的其它参数:
args:传给构造函数的参数 va_list。
返回值:
返回 Java 对象,如果无法构造该对象,则返回NULL
。
抛出:
InstantiationException:如果该类为接口或抽象类。
GetObjectClass
jclass GetObjectClass(JNIEnv *env, jobject obj);
参数:
env:JNI 接口指针。
返回值:
返回 Java 类对象。
IsInstanceOf
jboolean IsInstanceOf(JNIEnv *env, jobject obj,
jclass clazz);
参数:
env:JNI 接口指针。
返回值:
如果可将 obj
强制转换为 clazz
,则返回 JNI_TRUE
。否则返回 JNI_FALSE
。NULL
对象可强制转换为任何类。
IsSameObject
jbooleanIsSameObject(JNIEnv *env, jobject ref1,
jobject ref2);
测试两个引用是否引用同一 Java 对象。
参数:
env:JNI 接口指针。
ref2
:Java 对象。
返回值:
如果 ref1
和 ref2
引用同一 Java 对象或均为 NULL
,则返回 JNI_TRUE
。否则返回 JNI_FALSE
。
访问对象的域
GetFieldID
jfieldID GetFieldID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
返回类的实例(非静态)域的域 ID。该域由其名称及签名指定。访问器函数的Get<type>Field 及 Set<type>Field 系列使用域 ID 检索对象域。
GetFieldID()
将未初始化的类初始化。
GetFieldID()
不能用于获取数组的长度域。应使用GetArrayLength()
。
参数:
env:JNI 接口指针。
clazz
:Java 类对象。
返回值:
域 ID。如果操作失败,则返回NULL
。
抛出:
NoSuchFieldError:如果找不到指定的域。
ExceptionInInitializerError
:如果由于异常而导致类初始化程序失败。
Get<type>Field 例程
NativeType Get<type>Field(JNIEnv*env, jobject obj,
jfieldID fieldID);
该访问器例程系列返回对象的实例(非静态)域的值。要访问的域由通过调用GetFieldID()
而得到的域 ID 指定。
下表说明了 Get<type>Field 例程名及结果类型。应将 Get<type>Field 中的 type 替换为域的 Java 类型(或使用表中的某个实际例程名),然后将NativeType 替换为该例程对应的本地类型。
表 4-1 Get<type>Field 访问器例程系列 | |
参数:
env:JNI 接口指针。
返回值:
域的内容。
Set<type>Field 例程
void Set<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID,
NativeType value);
该访问器例程系列设置对象的实例(非静态)域的值。要访问的域由通过调用SetFieldID()
而得到的域 ID 指定。
下表说明了 Set<type>Field 例程名及结果类型。应将 Set<type>Field 中的 type 替换为域的 Java 类型(或使用表中的某个实际例程名),然后将NativeType 替换为该例程对应的本地类型。
表4-2 Set<type>Field 访问器例程系列 | |
参数:
env:JNI 接口指针。
调用实例方法
GetMethodID
jmethodID GetMethodID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
返回类或接口实例(非静态)方法的方法 ID。方法可在某个 clazz
的超类中定义,也可从 clazz
继承。该方法由其名称和签名决定。
GetMethodID()
可使未初始化的类初始化。
要获得构造函数的方法 ID,应将 <init>
作为方法名,同时将 void
(V
) 作为返回类型。
参数:
env:JNI 接口指针。
返回值:
方法 ID,如果找不到指定的方法,则为 NULL
。
抛出:
NoSuchMethodError:如果找不到指定方法。
ExceptionInInitializerError
:如果由于异常而导致类初始化程序失败。
Call<type>Method 例程
Call<type>MethodA 例程
Call<type>MethodV 例程
NativeType Call<type>Method(JNIEnv*env, jobject obj,
jmethodID methodID, ...);
NativeType Call<type>MethodA(JNIEnv *env, jobject obj,
jmethodID methodID, jvalue *args);
NativeType Call<type>MethodV(JNIEnv *env, jobject obj,
jmethodID methodID, va_list args);
这三个操作的方法用于从本地方法调用Java 实例方法。它们的差别仅在于向其所调用的方法传递参数时所用的机制。
这三个操作将根据所指定的方法 ID 调用 Java 对象的实例(非静态)方法。
参数 methodID
必须通过调用 GetMethodID()
来获得。
当这些函数用于调用私有方法和构造函数时,方法 ID 必须从 obj
的真实类派生而来,而不应从其某个超类派生。
Call<type>Method例程
编程人员应将要传给方法的所有参数紧跟着放在 methodID
参数之后。Call<type>Method 例程接受这些参数并将其传给编程人员所要调用的 Java 方法。
Call<type>MethodA 例程
编程人员应将要传给方法的所有参数放在紧跟在 methodID
参数之后的 jvalues
类型数组 args 中。Call<type>MethodA routine 接受这些数组中的参数并将其传给编程人员所要调用的 Java 方法。
Call<type>MethodV例程
编程人员将方法的所有参数放在紧跟着在 methodID
参数之后的 va_list
类型参数变量中。Call<type>MethodV routine 接受这些参数并将其传给编程人员所要调用的 Java 方法。
下表根据结果类型说明了各个方法调用例程。用户应将Call<type>Method 中的 type 替换为所调用方法的 Java 类型(或使用表中的实际方法调用例程名),同时将 NativeType 替换为该例程相应的本地类型。
表 4-3 实例方法调用例程 | |
| |
参数:
env:JNI 接口指针。
Call<type>Method例程的其它参数:
要传给 Java 方法的参数。
Call<type>MethodA例程的其它参数:
args:参数数组。
Call<type>MethodV例程的其它参数:
args:参数的 va_list。
返回值:
返回调用 Java 方法的结果。
抛出:
执行 Java 方法时抛出的异常。
CallNonvirtual<type>Method 例程
CallNonvirtual<type>MethodA 例程
CallNonvirtual<type>MethodV 例程
NativeType CallNonvirtual<type>Method(JNIEnv *env, jobject obj,
jclass clazz, jmethodID methodID, ...);
NativeType CallNonvirtual<type>MethodA(JNIEnv *env, jobject obj,
jclass clazz, jmethodID methodID, jvalue *args);
NativeType CallNonvirtual<type>MethodV(JNIEnv *env, jobject obj,
jclass clazz, jmethodID methodID, va_list args);
这些操作根据指定的类和方法 ID 调用某 Java 对象的实例(非静态)方法。参数 methodID
必须通过调用 clazz
类的GetMethodID()
获得。
CallNonvirtual<type>Method 和 Call<type>Method 例程系列并不相同。Call<type>Method 例程根据对象的类调用方法,而 CallNonvirtual<type>Method 例程则根据获得方法 ID 的(由 clazz
参数指定)类调用方法。方法 ID 必须从对象的真实类或其某个超类获得。
CallNonvirtual<type>Method例程
编程人员应将要传给方法的所有参数紧跟着放在 methodID
参数之后。CallNonvirtual<type>Method routine 接受这些参数并将其传给编程人员所要调用的 Java 方法。
CallNonvirtual<type>MethodA例程
编程人员应将要传给方法的所有参数放在紧跟在 methodID
参数之后的 jvalues
类型数组 args 中。CallNonvirtual<type>MethodAroutine 接受这些数组中的参数并将其传给编程人员所要调用的 Java 方法。
CallNonvirtual<type>MethodV例程
编程人员应将要传给方法的所有参数放在紧跟在 methodID
参数之后的 va_list
类型参数 args 中。CallNonvirtualMethodV routine 接受这些参数并将其传给编程人员所要调用的 Java 方法。
下表根据结果类型说明了各个方法调用例程。用户应将CallNonvirtual<type>Method 中的 type 替换为所调用方法的 Java 类型(或使用表中的实际方法调用例程名),同时将 NativeType 替换为该例程相应的本地类型。
参数:
env:JNI 接口指针。
clazz:
Java 类。
CallNonvirtual<type>Method例程的其它参数:
要传给 Java 方法的参数。
CallNonvirtual<type>MethodA例程的其它参数:
args:参数数组。
CallNonvirtual<type>MethodV例程的其它参数:
args:参数的 va_list
。
返回值:
调用 Java 方法的结果。
抛出:
执行 Java 方法时所抛出的异常。
访问静态域
GetStaticFieldID
jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
返回类的静态域的域 ID。域由其名称和签名指定。GetStatic<type>Field 和 SetStatic<type>Field 访问器函数系列使用域 ID 检索静态域。
GetStaticFieldID()
将未初始化的类初始化。
参数:
env:JNI 接口指针。
返回值:
域 ID。如果找不到指定的静态域,则为 NULL
。
抛出:
NoSuchFieldError:如果找不到指定的静态域。
ExceptionInInitializerError
:如果由于异常而导致类初始化程序失败。
GetStatic<type>Field 例程
NativeType GetStatic<type>Field(JNIEnv*env, jclass clazz,
jfieldID fieldID);
该访问器例程系列返回对象的静态域的值。要访问的域由通过调用GetStaticFieldID()
而得到的域 ID 指定。
下表说明了 GetStatic<type>Field 例程名及结果类型。应将 GetStatic<type>Field 中的 type 替换为域的 Java 类型(或使用表中的某个实际例程名),然后将NativeType 替换为该例程对应的本地类型。
表 4-5 GetStatic<type>Field 访问器例程系列 | |
参数:
env:JNI 接口指针。
返回值:
静态域的内容。
SetStatic<type>Field 例程
void SetStatic<type>Field(JNIEnv *env, jclass clazz,
jfieldID fieldID,
NativeType value);
该访问器例程系列设置对象的静态域的值。要访问的域由通过调用GetStaticFieldID()
而得到的域 ID 指定。
下表说明了 SetStatic<type>Field 例程名及结果类型。应将 SetStatic<type>Field 中的 type 替换为域的 Java 类型(或使用表中的某个实际例程名),然后将NativeType 替换为该例程对应的本地类型。
表4-6 SetStatic<type>Field 访问器例程系列 | |
参数:
env:JNI 接口指针。
clazz:Java 类对象。
调用静态方法
GetStaticMethodID
jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
GetStaticMethodID()
将未初始化的类初始化。
参数:
env:JNI 接口指针。
返回值:
方法 ID,如果操作失败,则为 NULL
。
抛出:
NoSuchMethodError:如果找不到指定的静态方法。
ExceptionInInitializerError
:如果由于异常而导致类初始化程序失败。
CallStatic<type>Method 例程
CallStatic<type>MethodA 例程
CallStatic<type>MethodV 例程
NativeType CallStatic<type>Method(JNIEnv*env, jclass clazz,
jmethodID methodID, ...);
NativeType CallStatic<type>MethodA(JNIEnv *env, jclass clazz,
jmethodID methodID, jvalue *args);
NativeType CallStatic<type>MethodV(JNIEnv *env, jclass clazz,
jmethodID methodID, va_list args);
这些操作将根据指定的方法 ID 调用 Java 对象的静态方法。methodID
参数必须通过调用GetStaticMethodID()
得到。
CallStatic<type>Method例程
编程人员应将要传给方法的所有参数紧跟着放在 methodID
参数之后。 CallStatic<type>Method routine 接受这些参数并将其传给编程人员所要调用的 Java 方法。
CallStatic<type>MethodA 例程
编程人员应将要传给方法的所有参数放在紧跟在 methodID
参数之后的 jvalues
类型数组 args 中。CallStaticMethodA routine 接受这些数组中的参数并将其传给编程人员所要调用的 Java 方法。
CallStatic<type>MethodV例程
编程人员应将要传给方法的所有参数放在紧跟在 methodID
参数之后的 va_list
类型参数 args 中。CallStaticMethodV routine 接受这些参数并将其传给编程人员所要调用的 Java 方法。
下表根据结果类型说明了各个方法调用例程。用户应将CallStatic<type>Method 中的 type 替换为所调用方法的 Java 类型(或使用表中的实际方法调用例程名),同时将 NativeType 替换为该例程相应的本地类型。
参数:
env:JNI 接口指针。
CallStatic<type>Method例程的其它参数:
要传给静态方法的参数。
CallStatic<type>MethodA例程的其它参数:
args:参数数组。
CallStatic<type>MethodV例程的其它参数:
args:参数的 va_list
。
返回值:
返回调用静态 Java 方法的结果。
抛出:
执行 Java 方法时抛出的异常。
字符串操作
NewString
jstring NewString(JNIEnv *env, const jchar *unicodeChars,
jsize len);
利用 Unicode 字符数组构造新的 java.lang.String
对象。
参数:
env:JNI 接口指针。
unicodeChars
:指向 Unicode 字符串的指针。
返回值:
Java 字符串对象。如果无法构造该字符串,则为 NULL
。
抛出:
OutOfMemoryError:如果系统内存不足。
GetStringLength
jsize GetStringLength(JNIEnv *env, jstring string);
参数:
env:JNI 接口指针。
返回值:
Java 字符串的长度。
GetStringChars
const jchar * GetStringChars(JNIEnv *env, jstring string,
jboolean *isCopy);
返回指向字符串的 Unicode 字符数组的指针。该指针在调用 ReleaseStringchars()
前一直有效。
如果 isCopy
非空,则在复制完成后将 *isCopy
设为 JNI_TRUE
。如果没有复制,则设为JNI_FALSE
。
参数:
env:JNI 接口指针。
返回值:
指向 Unicode 字符串的指针,如果操作失败,则返回NULL
。
ReleaseStringChars
void ReleaseStringChars(JNIEnv *env, jstring string,
const jchar *chars);
通知虚拟机平台相关代码无需再访问 chars
。参数 chars
是一个指针,可通过 GetStringChars()
从 string
获得。
参数:
env:JNI 接口指针。
NewStringUTF
jstring NewStringUTF(JNIEnv *env, const char *bytes);
利用 UTF-8 字符数组构造新 java.lang.String
对象。
参数:
env:JNI 接口指针。如果无法构造该字符串,则为 NULL
。
返回值:
Java 字符串对象。如果无法构造该字符串,则为 NULL
。
抛出:
OutOfMemoryError:如果系统内存不足。
GetStringUTFLength
jsize GetStringUTFLength(JNIEnv *env, jstring string);
参数:
env:JNI 接口指针。
返回值:
返回字符串的 UTF-8 长度。
GetStringUTFChars
const char* GetStringUTFChars(JNIEnv *env, jstring string,
jboolean *isCopy);
返回指向字符串的 UTF-8 字符数组的指针。该数组在被ReleaseStringUTFChars()
释放前将一直有效。
如果 isCopy
不是 NULL
,*isCopy
在复制完成后即被设为 JNI_TRUE
。如果未复制,则设为 JNI_FALSE
。
参数:
env:JNI 接口指针。
返回值:
指向 UTF-8 字符串的指针。如果操作失败,则为 NULL
。
ReleaseStringUTFChars
void ReleaseStringUTFChars(JNIEnv *env, jstring string,
const char *utf);
通知虚拟机平台相关代码无需再访问 utf
。utf
参数是一个指针,可利用 GetStringUTFChars()
从 string
获得。
参数:
env:JNI 接口指针。
数组操作
GetArrayLength
jsize GetArrayLength(JNIEnv *env, jarray array);
参数:
env:JNI 接口指针。
返回值:
数组的长度。
NewObjectArray
jarray NewObjectArray(JNIEnv *env, jsize length,
jclass elementClass, jobject initialElement);
构造新的数组,它将保存类 elementClass
中的对象。所有元素初始值均设为 initialElement
。
参数:
env:JNI 接口指针。
返回值:
Java 数组对象。如果无法构造数组,则为 NULL
。
抛出:
OutOfMemoryError:如果系统内存不足。
GetObjectArrayElement
jobject GetObjectArrayElement(JNIEnv *env,
jobjectArray array, jsize index);
返回 Object
数组的元素。
参数:
env:JNI 接口指针。
返回值:
Java 对象。
抛出:
ArrayIndexOutOfBoundsException:如果 index
不是数组中的有效下标。
SetObjectArrayElement
void SetObjectArrayElement(JNIEnv *env, jobjectArray array,
jsize index, jobject value);
参数:
env:JNI 接口指针。
抛出:
ArrayIndexOutOfBoundsException:如果 index
不是数组中的有效下标。
ArrayStoreException
:如果 value
的类不是数组元素类的子类。
New<PrimitiveType>Array 例程
ArrayType New<PrimitiveType>Array(JNIEnv*env, jsize length);
用于构造新基本类型数组对象的一系列操作。表 4-8 说明了特定的基本类型数组构造函数。用户应把New<PrimitiveType>Array 替换为某个实际的基本类型数组构造函数例程名(见下表),然后将 ArrayType替换为该例程相应的数组类型。
表 4-8 New<PrimitiveType>Array 数组构造函数系列 | |
jfloatArray | |
参数:
env:JNI 接口指针。
返回值:
Java 数组。如果无法构造该数组,则为 NULL
。
Get<PrimitiveType>ArrayElements 例程
NativeType *
Get<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array, jboolean*isCopy);
一组返回基本类型数组体的函数。结果在调用相应的 Release<PrimitiveType>ArrayElements()函数前将一直有效。由于返回的数组可能是 Java 数组的副本,因此对返回数组的更改不必在基本类型数组中反映出来,直到调用了Release<PrimitiveType>ArrayElements()。
如果 isCopy
不是 NULL
,*isCopy
在复制完成后即被设为 JNI_TRUE
。如果未复制,则设为 JNI_FALSE
。
- 将 Get<PrimitiveType>ArrayElements 替换为表中某个实际的基本类型元素访问器例程名。
- 将 ArrayType 替换为对应的数组类型。
- 将 NativeType 替换为该例程对应的本地类型。
不管布尔数组在 Java 虚拟机中如何表示,GetBooleanArrayElements()
将始终返回一个 jbooleans
类型的指针,其中每一字节代表一个元素(开包表示)。内存中将确保所有其它类型的数组为连续的。
表4-9 Get<PrimitiveType>ArrayElements 访问器例程系列 | ||
参数:
env:JNI 接口指针。
返回值:
返回指向数组元素的指针,如果操作失败,则为 NULL
。
Release<PrimitiveType>ArrayElements 例程
void Release<PrimitiveType>ArrayElements(JNIEnv *env,
ArrayType array,
NativeType *elems, jintmode);
通知虚拟机平台相关代码无需再访问 elems
的一组函数。elems
参数是一个通过使用对应的Get<
PrimitiveType>
ArrayElements() 函数由 array 导出的指针。必要时,该函数将把对 elems
的修改复制回基本类型数组。
mode
参数将提供有关如何释放数组缓冲区的信息。如果elems
不是 array
中数组元素的副本,mode
将无效。否则,mode
将具有下表所述的功能:
表 4-10 基本类型数组释放模式 | |
多数情况下,编程人员将把“0”传给 mode
参数以确保固定的数组和复制的数组保持一致。其它选项可以使编程人员进一步控制内存管理,但使用时务必慎重。
下表说明了构成基本类型数组撤消程序系列的特定例程。应进行如下替换;
- 将 Release<PrimitiveType>ArrayElements 替换为表 4-11 中的某个实际基本类型数组撤消程序例程名。
- 将 ArrayType 替换为对应的数组类型。
- 将 NativeType 替换为该例程对应的本地类型。
表 4-11 Release<PrimitiveType>ArrayElements 数组例程系列 | ||
参数:
env:JNI 接口指针。
Get<PrimitiveType>ArrayRegion 例程
void Get<PrimitiveType>ArrayRegion(JNIEnv *env,
ArrayType array,
jsize start, jsize len,
NativeType *buf);
将基本类型数组某一区域复制到缓冲区中的一组函数。
下表说明了特定的基本类型数组元素访问器。应进行如下替换:
- 将 Get<PrimitiveType>ArrayRegion 替换为表 4-12 中的某个实际基本类型元素访问器例程名。
- 将 ArrayType 替换为对应的数组类型。
- 将 NativeType 替换为该例程对应的本地类型。
表 4-12 Get<PrimitiveType>ArrayRegion 数组访问器例程系列 | ||
参数:
env:JNI 接口指针。
抛出:
ArrayIndexOutOfBoundsException:如果区域中的某个下标无效。
Set<PrimitiveType>ArrayRegion 例程
void Set<PrimitiveType>ArrayRegion(JNIEnv *env,
ArrayType array,
jsize start, jsize len,
NativeType *buf);
下表说明了特定的基本类型数组元素访问器。应进行如下替换:
- 将 Set<PrimitiveType>ArrayRegion 替换为表中的实际基本类型元素访问器例程名。
- 将 ArrayType 替换为对应的数组类型。
- 将 NativeType 替换为该例程对应的本地类型。
表 4-13 Set<PrimitiveType>ArrayRegion 数组访问器例程系列 | ||
参数:
env:JNI 接口指针。
array
: Java 数组。
抛出:
ArrayIndexOutOfBoundsException:如果区域中的某个下标无效。
注册本地方法
RegisterNatives
jint RegisterNatives(JNIEnv *env, jclass clazz,
const JNINativeMethod *methods, jint nMethods);
向 clazz
参数指定的类注册本地方法。methods
参数将指定 JNINativeMethod
结构的数组,其中包含本地方法的名称、签名和函数指针。nMethods
参数将指定数组中的本地方法数。JNINativeMethod
结构定义如下所示:
typedef struct {
char *name;
char *signature;
void *fnPtr;
} JNINativeMethod;
函数指针通常必须有下列签名:
ReturnType (*fnPtr)(JNIEnv *env, jobject objectOrClass, ...);
参数:
env:JNI 接口指针。
clazz:Java 类对象。
返回值:
成功时返回 "0";失败时返回负数。
抛出:
NoSuchMethodError:如果找不到指定的方法或方法不是本地方法。
UnregisterNatives
jint UnregisterNatives(JNIEnv *env, jclass clazz);
取消注册类的本地方法。类将返回到链接或注册了本地方法函数前的状态。
该函数不应在常规平台相关代码中使用。相反,它可以为某些程序提供一种重新加载和重新链接本地库的途径。
参数:
env:JNI 接口指针。
clazz:Java 类对象。
返回值:
成功时返回“0”;失败时返回负数。
监视程序操作
MonitorEnter
jint MonitorEnter(JNIEnv *env, jobject obj);
进入与 obj
所引用的基本 Java 对象相关联的监视程序。
每个 Java 对象都有一个相关联的监视程序。如果当前线程已经拥有与obj
相关联的监视程序,它将使指示该线程进入监视程序次数的监视程序计数器增 1。如果与 obj
相关联的监视程序并非由某个线程所拥有,则当前线程将变为该监视程序的所有者,同时将该监视程序的计数器设置为 1。如果另一个线程已拥有与 obj
关联的监视程序,则在监视程序被释放前当前线程将处于等待状态。监视程序被释放后,当前线程将尝试重新获得所有权。
参数:
env:JNI 接口指针。
obj
:常规 Java 对象或类对象。
返回值:
成功时返回“0”;失败时返回负数。
MonitorExit
jint MonitorExit(JNIEnv *env, jobject obj);
当前线程必须是与 obj
所引用的基本 Java 对象相关联的监视程序的所有者。线程将使指示进入监视程序次数的计数器减 1。如果计数器的值变为 0,当前线程释放监视程序。
参数:
env:JNI 接口指针。
返回值:
成功时返回“0”;失败时返回负数。
Java 虚拟机接口
GetJavaVM
jint GetJavaVM(JNIEnv *env, JavaVM **vm);
返回与当前线程相关联的 Java 虚拟机接口(用于调用 API 中)。结果将放在第二个参数 vm
所指向的位置。
参数:
env:JNI 接口指针。
返回值:
成功时返回“0”;失败时返回负数。