JNI之四:JNI函数(下)

相关链接:JNI函数(上)


对象操作


AllocObject

jobject AllocObject(JNIEnv *env, jclass clazz);

不调用构造函数的情况下,分配一个新的对象。返回对象引用。

注意:java语言规范,12.6.1 实现finalize:“在对象o上调用了Object的构造方法,且构造方法调用成功,否则对象o不可终结”。因为AllocObject()未调用构造方法,所以通过此函数创建的对象不符合终结机制(finalization),不会被终结。

clazz参数不可为数组class。

函数表27

参数

clazz:Java class对象引用。不可为空。

返回值

返回java对象,如果对象不能被构造,则返回null。

异常

InstantiationException:如果类是接口或抽象类。
OutOfMemoryError:系统内存不足。


NewObject, NewObjectA, NewObjectV

jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...);

jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);

jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);

构造新的java对象。methodID表示要调用的构造方法。ID必须通过调用GetMethodID()获得,方法名传 <init>,方法签名为void(V)

clazz参数不可为数组class。

NewObject

程序员将所有参数直接跟在methodID参数后面传入。 NewObject()接受这些参数并将它们传入程序员想调用的Java方法中去。

函数表28

NewObjectA

程序员直接将构造方法需要的参数放在名为argsjvalues数组中,跟在methodID后面传入。NewObjectA() 接受这个数组作为参数,并将他们传入要调用的Java方法中。

函数表30

NewObjectV

传入va_list类型的构造函数参数args。


GetObjectClass

jclass GetObjectClass(JNIEnv *env, jobject obj);

返回对象的class。

函数表31

obj: java对象, 不可为NULL


GetObjectRefType

jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj);

返回obj对象的引用类型。obj参数可为局部引用,全局引用,全局弱引用,或null。

函数表232

参数

obj:局部引用,全局引用或全局弱引用。

返回值

此函数返回以下jobjectRefType的枚举值:

JNIInvalidRefType    = 0//obj是无效的引用
JNILocalRefType      = 1//obj是局部引用
JNIGlobalRefType     = 2//obj是全局引用
JNIWeakGlobalRefType = 3//如果obj是全局弱引用

无效引用是一个无效句柄的引用。即obj指针地址未指向一个通过Ref创建函数之一分配的内存或JNI返回的内存地址。

因此,NULL是一个无效引用, GetObjectRefType(env,NULL)将返回JNIInvalidRefType

换句话说,null引用是一个指向null的引用,将返回最开始创建为null的引用。

GetObjectRefType不能用在已删除的引用上。

由于引用通常被实现为指向能潜在地被任何VM引用分配服务重用的内存数据结构,一旦删除,GetObjectRefType的返回值就不是指定的了。


IsInstanceOf

jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz);

测试一个对象是否是某个class的实例。

函数表32

参数

obj:Java对象,可能为空。
clazz:Java class对象,不可为空。

返回值

如果obj可以被强转为clazz,则返回JNI_TRUE,否则返回JNI_FALSENULL对象可强转为任何类。


IsSameObject

jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2);

测试两个引用是否指向同一个Java对象。

函数表24

ref1,ref2皆可为null。

如果ref1,ref2指向同一个Java对象或者二者皆为null,则返回JNI_TRUE;否则返回JNI_FALSE。


访问对象域


GetFieldID

jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

函数表94

返回类的实例域(非静态域)ID,该字段由其名称和签名指定。Get<type>FieldSet<type>Field的访问器函数族使用ID来获取对象成员。

GetFieldID()导致未被初始化的类被初始化。
GetFieldID()不能用来获取数组的长度字段,如需获取数组长度,使用GetArrayLength()函数。

参数

clazz:Java class对象,不可为空。
name:字段名称(0-结束符 MUTF-8字符串),不可为空。
sig:字段签名(0-结束符 MUTF-8字符串),不可为空。

返回值

成功则返回字段ID,如果操作失败,则返回NULL。

异常

NoSuchFieldError:如果指定字段找不到。
ExceptionInInitializerError:由于异常导致类初始化失败。
OutOfMemoryError:系统内存不足。


Get<type>Field例程

NativeType Get<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID);

此程序族返回对象实例域的值,要访问的字段的ID通过GetFieldID()方法获取。

下表描述了Get<type>Field例程的名称和返回值,用字段的Java类型替换Get<type>Field中的type,或者用下表中的名称,并且用替换NativeType为相应例程的native type。

GetField例程名称Native类型
GetObjectField()jobject
GetBooleanField()jboolean
GetByteField()jbyte
GetCharField()jchar
GetShortField()jshort
GetIntField()jint
GetLongField()jlong
GetFloatField()jfloat
GetDoubleField()jdouble
链接

Get<type>Field程序族各自对应的JNI接口函数表索引:

GetField例程名称索引
GetObjectField()95
GetBooleanField()96
GetByteField()97
GetCharField()98
GetShortField()99
GetIntField()100
GetLongField()101
GetFloatField()102
GetDoubleField()103

Set<type>Field 例程

void Set<type>Field(JNIEnv *env, jobject obj, jfieldID fieldID, NativeType value);

此访问器家族修改对象的实例域,通过调用GetFieldID()获得访问指定字段的字段id。

下表展示了Set<type>Field例程的名称和类型,使用它们时应该将type替换字段的java类型,或者使用表中的实际例程名称,并替换NativeType为相应的native类型。

SetField例程名称Native类型
SetObjectField()jobject
SetBooleanField()jboolean
SetByteField()jbyte
SetCharField()jchar
SetShortField()jshort
SetIntField()jint
SetLongField()jlong
SetFloatField()jfloat
SetDoubleField()jdouble
链接
SetField例程名称Index
SetObjectField()104
SetBooleanField()105
SetByteField()106
SetCharField()107
SetShortField()108
SetIntField()109
SetLongField()110
SetFloatField()111
SetDoubleField()112

调用静态方法


GetStaticMethodID

jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

根据方法名称和签名,返回静态方法id。GetStaticMethodID()将引发未初始化的类初始化。

函数表113

参数

clazz:class对象,不可为空
name:静态方法名称,不可为空
sig:方法签名,不可为空

返回值

成功,返回方法id;失败,返回NULL。

异常

NoSuchMethodError:指定的静态方法未找到
ExceptionInInitializerError:类初始化异常
OutOfMemoryError:内存不足


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()生成,且方法id必须有clazz派生,而不是它的某个父类。

CallStatic<type>Method例程

将所有参数跟在methodID后面,CallStatic<type>Method例程接受可变参数,然后将他们传入期望调用的java方法。

CallStatic<type>MethodA 例程

将参数放在一个jvalues类型的args数组中,跟在methodID参数后面。CallStaticMethodA例程接受将参数至于数组中,然后将他们传入期望调用的java方法中。

CallStatic<type>MethodV例程

将参数至于va_list中,CallStaticMethodV接受这些参数,然后将他们传入期望调用的java方法中。

下表根据result类型描述每一个方法调用,你应该用方法的java类型替换CallStatic<type>Method中的type,或者表中实际的方法调用例程名称,并替换NativeType为例程对应的native类型。

CallStaticMethod例程名称Native类型
CallStaticVoidMethod()
CallStaticVoidMethodA()
CallStaticVoidMethodV()
void
CallStaticObjectMethod()
CallStaticObjectMethodA()
CallStaticObjectMethodV()
jobject
CallStaticBooleanMethod()
CallStaticBooleanMethodA()
CallStaticBooleanMethodV()
jboolean
CallStaticByteMethod()
CallStaticByteMethodA()
CallStaticByteMethodV()
jbyte
CallStaticCharMethod()
CallStaticCharMethodA()
CallStaticCharMethodV()
jchar
CallStaticShortMethod()
CallStaticShortMethodA()
CallStaticShortMethodV()
jshort
CallStaticIntMethod()
CallStaticIntMethodA()
CallStaticIntMethodV()
jint
CallStaticLongMethod()
CallStaticLongMethodA()
CallStaticLongMethodV()
jlong
CallStaticFloatMethod()
CallStaticFloatMethodA()
CallStaticFloatMethodV()
jfloat
CallStaticDoubleMethod()
CallStaticDoubleMethodA()
CallStaticDoubleMethodV()
jdouble

链接

CallStaticMethod例程名称函数索引
CallStaticVoidMethod()
CallStaticVoidMethodA()
CallStaticVoidMethodV()
141
143
142
CallStaticObjectMethod()
CallStaticObjectMethodA()
CallStaticObjectMethodV()
114
116
115
CallStaticBooleanMethod()
CallStaticBooleanMethodA()
CallStaticBooleanMethodV()
117
119
118
CallStaticByteMethod()
CallStaticByteMethodA()
CallStaticByteMethodV()
120
122
121
CallStaticCharMethod()
CallStaticCharMethodA()
CallStaticCharMethodV()
123
125
124
CallStaticShortMethod()
CallStaticShortMethodA()
CallStaticShortMethodV()
126
128
127
CallStaticIntMethod()
CallStaticIntMethodA()
CallStaticIntMethodV()
129
131
130
CallStaticLongMethod()
CallStaticLongMethodA()
CallStaticLongMethodV()
132
134
133
CallStaticFloatMethod()
CallStaticFloatMethodA()
CallStaticFloatMethodV()
135
137
136
CallStaticDoubleMethod()
CallStaticDoubleMethodA()
CallStaticDoubleMethodV()
138
140
139

参数

methodID:有效的静态方法id
CallStatic<type>Method例程可选参数:该静态方法的参数
CallStatic<type>MethodA例程可选参数args:一组参数
CallStatic<type>MethodV例程可选参数args:va_list参数

返回值

调用的静态方法的返回值。

异常

java方法执行期间引发的异常。


String操作

此规范不假设JVM内部如何表示字符串。下列操作返回Strings:

  • GetStringChars()
  • GetStringUTFChars()
  • GetStringRegion()
  • GetStringUTFRegion()
  • GetStringCritical()

因此不强制null中断。程序员应通过GetStringLength()GetStringUTFLength()确定缓冲容量大小。


NewString

jstring NewString(JNIEnv *env, const jchar *unicodeChars, jsize len);

由Unicode字符构造新的 java.lang.String 对象。

参数

unicodeChars :指向Unicode字符串。可为空,为空时len必须为0。
len:Unicode字符串长度。可为0。

返回值

Java String对象,如果字符串无法被构造,返回null。

异常

OutOfMemoryError :系统内存不足时。


GetStringLength

jsize GetStringLength(JNIEnv *env, jstring string);

返回Java String的长度(Unicode字符的数量)。


GetStringChars

const jchar * GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy);

返回指向String的Unicode字符数组的指针。此指针在ReleaseStringChars()调用之前始终有效。如果isCopy字段不为空,则 *isCopy设置为 JNI_TRUE