JNI开发笔记(三)

在JNI层都会用jobject表示对象的数据类型
JNIEnv操作 jobject  操作jobject的本质是操作这些对象的成员变量和成员函数

通过JNIEnv输出CallVoidMethod,再把jobject,jMethodID和对应的参数传入,JNI层就能调用Java对象的函数
实际上JNIEnv输出一系列类似CallVoidMethod的函数

  NativeType CallMethod(JNIEnv *env, jobject obj, jmethod methodID, ...);
通过JNIEnv操作jobject的成员函数,通过jfieldID操作jobject的成员变量
//获得 fieldID 后,可调用GetField系统函数获取jobject对应的成员变量函数
NativeType GetField(JNIEnv *env, jobject obj, jfieldID fieldID)

GetObjectField() SetObjectField()
GetBooleanField() SetBooleanField()
GetByteField() SetByteField()
GetCharField() SetCharField()
GetShortField() SetShortField()
GetIntField() SetIntField()
GetLongField() SetLongField()
GetFloatField() SetFloatField()
GetDoubleField() SetDoubleField()


Java创建的对象最后是由垃圾回收期来回收释放内存

对一个引用类型执行赋值操作,垃圾回收只会保证那些没有被引用的对象才会被清理。但在JNI层使用赋值,是不会增加引用计数的。
    save_thiz = thiz;   //这种赋值不会增加jobject的引用计数
JNI技术提供了3种类型的引用
  Local Reference:本地引用,包括函数调用时传入的jobject和在JNI层函数中创建的jobject。最大特点一旦JNI层函数返回,这些jobject就可能被垃圾回收。
  Global Reference:全局引用,不主动释放永不回收。
  Weak Global Reference:弱全局引用,一种特殊的Global Reference,可能会被回收,在使用之前,需要调用JNIEnv的IsSameObject判断是否被回收了


static jobject save_thiz = NULL;
static void android_media_MediaScanner_processFile
(JNIEnv *env, jobject thiz, jstring path, jstring mimeType, jobject client)
{
//保存Java层传入的jobject对象,代表MediaScanner对象
	save_thiz = thiz;
}


void callMediaScanner()
{
	//save_thiz 对应Java层的MediaScanner很可能被垃圾回收了,保存的这个jobject可能是一个野指针
}
每当JNI层想保存Java层中某个对象时,就可以使用Global Reference,使用后记得释放。



JNI中的异常处理
异常不会中断本地函数的执行,直到从JNI返回到Java层后,虚拟机才抛出这个异常。虽然在JNI层中产生的异常不会中断本地函数的运行,但是一旦产生异常后,只能做一些资源清理的工作了(释放全局引用,或ReleaseStringChars)。
 JNI层函数可以在代码中截获和修改这些异常,提供了3个函数:
ExceptionOccured,判断异常发生
ExceptionClear,清理当前JNI层发生的异常
ThrowNew,用来向Java层抛出异常


你可能感兴趣的:(Android)