Native开发过程中容易忽略的注意事项
在进行native开发时,还需要注意以下事项:
-
不要在native方法中直接抛出Java异常。应该使用JNIEnv中提供的函数来创建和抛出Java异常。
-
不要在native方法中缓存JNIEnv指针,因为它可能会在运行时被释放或重载。
-
在native方法中访问Java对象时,需要使用JNI提供的函数来获取和操作Java对象,避免直接访问Java对象的内部成员。
-
注意本地库和Java代码的链接方式和加载顺序,避免出现库加载失败或符号冲突等问题。
-
在本地库中使用动态内存分配时,需要注意及时释放分配的内存,避免内存泄漏和程序崩溃。
以下是一些常见的native开发注意事项的具体示例:
- 不要在native方法中直接抛出Java异常
c++
JNIEXPORT void JNICALL
Java_com_example_MyClass_nativeMethod(JNIEnv *env, jobject obj) {
jclass exceptionClass = env->FindClass("java/lang/Exception");
env->ThrowNew(exceptionClass, "Native method exception");
// 抛出异常后必须返回,否则代码将继续执行
return;
}
- 不要在native方法中缓存JNIEnv指针
c++
JNIEXPORT void JNICALL
Java_com_example_MyClass_nativeMethod(JNIEnv *env, jobject obj) {
jclass cls = env->GetObjectClass(obj);
jmethodID methodID = env->GetMethodID(cls, "javaMethod", "()V");
// 缓存JNIEnv指针,容易出现问题
JNIEnv *cachedEnv = env;
cachedEnv->CallVoidMethod(obj, methodID);
// 应该每次都重新获取JNIEnv指针
env->CallVoidMethod(obj, methodID);
return;
}
- 在native方法中访问Java对象时,使用JNI提供的函数来获取和操作Java对象
c++
JNIEXPORT void JNICALL
Java_com_example_MyClass_nativeMethod(JNIEnv *env, jobject obj, jobject jobj) {
// 直接访问Java对象的内部成员是不安全的
jclass cls = env->GetObjectClass(jobj);
jfieldID fieldID = env->GetFieldID(cls, "field", "Ljava/lang/String;");
jstring str = (jstring)env->GetObjectField(jobj, fieldID);
// 应该使用JNI函数来获取和操作Java对象
jclass stringCls = env->FindClass("java/lang/String");
jmethodID lengthID = env->GetMethodID(stringCls, "length", "()I");
int length = env->CallIntMethod(str, lengthID);
return;
}
- 注意本地库和Java代码的链接方式和加载顺序
在Android.mk或CMakeLists.txt中设置链接选项和库依赖,例如:
makefile
LOCAL_LDLIBS := -llog -landroid
LOCAL_SHARED_LIBRARIES := libfoo
在Java代码中加载本地库,例如:
java
static {
System.loadLibrary("mylib");
}
- 在本地库中使用动态内存分配时,注意及时释放分配的内存
c++
JNIEXPORT jbyteArray JNICALL
Java_com_example_MyClass_nativeMethod(JNIEnv *env, jobject obj, jint size) {
jbyte *buffer = new jbyte[size];
// 使用完毕后必须释放内存,避免内存泄漏
jbyteArray result = env->NewByteArray(size);
env->SetByteArrayRegion(result, 0, size, buffer);
delete[] buffer;
return result;
}