JNI 中构造 Java 对象的注意点
Android NDK,在 JNI 中构造 Java 对象时有以下几点需要注意的:
1. FindClass 要在 Java VM 线程中调用
FindClass 只能在 Java VM 线程中调用,所以如果要在子线程中创建 Java 对象的话,需要把结果保存下来,使用的方式是用 NewGlobalRef 创建全局引用。
jclass javaClassLocal = env->FindClass(kAndroidJavaClass);
if (javaClassLocal) {
m_javaClassLocal = (jclass)env->NewGlobalRef(javaClassLocal);
env->DeleteLocalRef(javaClassLocal);
}
全局引用要在程序退出前销毁。
if (m_javaClassLocal) env->DeleteGlobalRef(m_javaClassLocal);
2. GetFieldID 中表示类型的方式与 FindClass 不同
FindClass 中使用的是类型名称,而 GetFieldID 中如果使用的是类,则需要在类名前加上 L,结尾加上分号。
env->FindClass("com/example/myclass");
env->GetFieldID(jclz, "_mydata", "Lcom/example/myclass;");
3. AttachCurrentThread 不可嵌套使用
在非 Java VM 线程中使用 JNI 需要通过 AttachCurrentThread 来获取 JNIEnv 指针,但是 AttachCurrentThread 函数不能递归重复使用。需要使用 DetachCurrentThread 释放后才能再次调用。