引言
在《Android NDK 使用指南(进阶篇一)》中,介绍了JNI的工作流程及其中的核心部分代码的详细解释,接下来将介绍一些常用的使用技巧,帮助开发人员提高开发效率和代码质量。
绑定Native层和Java层对象
public class CTest {
public CTest() {
JNIEnv *env = NULL;
jclass clazz = NULL;
jmethodID method_class_constructor = NULL;
jvm_ = GetJVM();
jvm_->AttachCurrentThread(&env, NULL);
method_class_constructor = env->GetMethodID(clazz, "<init>", "(J)V"); // 调用java对象构造函数
jlong addr = (intptr_t)this;
object_ = env->NewObject(clazz, method_class_constructor, addr); // 将当前对象地址传给java
object_ = env->NewGlobalRef(object_); // 将本地引用转换为全局引用
jvm_->DetachCurrentThread();
}
public std::string CFunction(std::string str) {
return str;
}
}
public class JavaTest {
private long nativeAddr; // 存储c++对象地址
public JavaTest(long nativeAddr) {
this.nativeAddr = nativeAddr;
}
public native void nativeFunction(long nativeAddr, String str); // native方法
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_app_java_test_nativeFunction(JNIEnv *env, jobject obj, jlong native_addr, jstring str) {
CTest *c = (CTest*)native_addr; // 获取原始对象
c->CFunction(str);
}
绑定Native层和Java层对象,具有以下几个显著的优点:
1. 性能优化
- 计算密集型任务:某些计算密集型任务(如图像编解码)在C/C++中执行效率更高。通过JNI可以将这些任务委托给本地代码,从而提升应用的整体性能。
- 减少内存分配:在Native层直接操作对象引用可以减少内存分配和垃圾回收的压力,因为对象的内存管理可以在Native层进行控制,而不是在Java层进行频繁的对象创建和销毁。
2. 代码复用和整合
- 在Java和Native层之间共享对象可以避免在两者之间重复编写相同的逻辑或数据处理代码,减少了代码重复和维护成本。