NDK内存管理-引用

xiaoeryu Lv5

NDK中的内存管理:C/C++的new/malloc和delete/free以及JNI引用。

Java和C/C++内存管理的区别

三种引用的区别

在JNI规范中定义了三种引用:

  • 局部引用(LocalReference)
  • 全局引用(Global Reference)
  • 若全局引用(Weak Global Reference)

因生命周期限制,不能在外部定义一个全局变量接受局部引用,在其他函数使用

之前多线程的代码中使用过,例如:

jobject appClassloader = env->NewGlobalRef(TestJclass);
// 使用方式:用参数传递,或者定义一个全局变量接收也行
    pthread_create(&thread, nullptr, threadtest, appClassloader);

env->DeleteGlobalRef(appClassloader);

作用域和全局引用是相同的,但是如果内存紧张可能会被ART给释放掉

再JNI种局部引用的创建也是受局部引用表限制的

for (int i = 0; i < 2048; ++i) {
    jstring content = env->NewStringUTF("test localreference");
    __android_log_print(4, "xiaoeryu->jni", "localreference number->%d", i);
}

例如这样只创建不删除,有些引用会被自动释放掉

需要在每次循环结束加上env->DeleteLocalRef(content);

测试了之后发现加上比之前好点但是也不稳定,有些变量还是会被自动释放掉,所以还是尽量不要这样使用。

EnsureLocalCapacity

  • 创建多引用之前可以用EnsureLocalCapacity()测试一下能否创建成功
int len = 10;
if (env->EnsureLocalCapacity(len) == 0){
    for (int i = 0; i < len; ++i) {
        jstring content = env->NewStringUTF("test EnsureLocalCapacity");
        __android_log_print(4, "xiaoeryu->jni", "EnsureLocalCapacity number->%d", i);
    }
}

PushLocalFrame/PopLocalFrame

  • 局部引用堆栈的创建和销毁
jobject testPushAndPopLocalFrame(JNIEnv* env){
    jobject result = nullptr;
    if (env->PushLocalFrame(20) == 0){
        for (int i = 0; i < 18; ++i) {
            jstring tmp = env->NewStringUTF("xiaoeryu");
        }
        jstring tmp_1 = env->NewStringUTF("result_1");
        jstring tmp_2 = env->NewStringUTF("result_2");
        result = env->PopLocalFrame(tmp_1);     // 保留tmp_1
    }
    return result;
}
  • 标题: NDK内存管理-引用
  • 作者: xiaoeryu
  • 创建于 : 2023-10-17 23:52:33
  • 更新于 : 2023-10-19 11:10:39
  • 链接: https://github.com/xiaoeryu/2023/10/17/NDK内存管理-引用/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
此页目录
NDK内存管理-引用