如果调用jni env的接口抛出异常,首先它不会立刻抛出异常,根据本人分析,它会在两种情况下抛出:
1、jni返回时,如果env是jni函数返回的最后一句,那么返回时,它会抛出异常。这时java端能收到异常,然后系统提示已停止运行
2、再调下一个env时抛出异常,这时java端收不到异常,程序闪退。Log提示:jni method called with pending exception。(本人曾经单步调试,一直以为是下一句出错了,机缘巧合下,无奈使用log调试,无意中发现这个log,意思是jni方法调用时已经有异常了。所以也就是说,上一句代码出错了。)。
总结:env调用出错时,不会马上报错,而会延迟报错。查错时,仔细看ddms 的log,这时单步和打log方式可能会误导判断。
----------------------------------------------------------------------------------------------------------------------
AllocObejct 和 NewObject的区别
前者创建对象,但不调用构造函数,即当真正需要使用该对象时,需要调用构造函数来初始化。不常用,用作延迟加载
后者调用指定的构造函数来创建对象,常用。
NewObject
NewObjectV
NewObjectA
区别
加V的表示后面带va_args参数
加A的表示后面带args参数
区别只在输入参数,核心代码跑的都是一样的。一般常用NewObject
allocObject使用举例:
class clazz = env->FindClass("java/lang/ABC");
jmethodID con = env->GetMethodID(clazz ,"<init>", "()V");
jobject obj = env->AllocObject(clazz);//do something
...
...
env->CallNovirtualVoidMethod(obj ,class,con);
----------------------------------------------------------------------------------------------------------------------
内部类的构造函数
静态内部类
class签名: com/ty/jni/JNI$ABC
注:
包名com.ty.jni
类名JNI
内部类ABC
class clazz = env->FindClass("com/ty/jni/JNI$ABC");
jmethodID con = env->GetMethodID(clazz ,"<init>", "()V");
jobject obj = env->newObject(class,con);
内部类
由于内部类隐含外部类的引用,所以构造函数有隐藏参数:外部类的引用
class签名: com/ty/jni/JNI$ABC
注:
包名com.ty.jni
类名JNI
内部类ABC
class clazz = env->FindClass("com/ty/jni/JNI$ABC");
jmethodID con = env->GetMethodID(clazz ,"<init>", "(Lcom/ty/jni/JNI;)V");
jobject obj = env->newObject(class,con,external_obj);external_obj为外部类引用,获取方法不一而足
总结:
所有类构造函数的名称都叫<init>
包名的签名接口为"/"
内部类与外部类的签名接口为“$”
参考:
http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/jniTOC.html
http://hi.baidu.com/mysecretmood/item/6c465e216cb246d50e37f9cf