zoukankan      html  css  js  c++  java
  • android 内存泄露之jni local reference table overflow (max=512)

    在android项目中要实现一个需求

    为了性能的要求只能用c代码来实现功能。

    这样就牺牲了java跨平台性。

    通过加载.so的方式,把用c实现的模块集成到app中。

    android提供jni层,作为一个适配器。

    可以在java层调用c接口,在jni层可以通过java提供的反射机制调用java接口和创建java对象。

    最后需求完成了,自测也没问题,嘻嘻,自己也开心了一下,但是提交测试后,测试人员马上报了一个bug。

    出现local reference table overflow (max=512)这样的一个错误。我去,尽然出现了崩溃。

    google和百度了半天,才发现原来发生了jni层的内存泄露,导致了崩溃。

    jni层到底出现了啥内存泄露????

    从java代码进入jni层本地代码调用时,Dalvik就创建了一张local reference表来存储local reference,这张表

    的表项数有最大值限制,一般最大为都是512个,local reference表只有当退出jni层代码的调用是才会清除掉。

    当表项数超过最大值限制时,Dalvik就会抛出异常,导致了崩溃。

    何为local reference????

    他是在native代码层他是一个本地变量和java对象的引用。

    JNIEXPORT jint JNICALL Java_com_print(JNIEnv *env, jobject obj){

      char data[] = "daffdasf";

        jstring content = (*env)->NewStringUTF(env, data);

    }

    变量content在 函数Java_com_print中是一个本地变量并且是String对象一个引用。所以会在local reference table

    中追加一个表项来指向java对象。

    其实每次进入native代码都会存在一个全局指向local reference table起始位置的ptr变量。

    而上面函数中的content只是代表一个在local reference table中的偏移,通过ptr + content偏移

    从local reference table获取java对象的值。

    什么原因会发生local reference table overflow?????

    那就是在一个循环中不断的创建local reference,而没有调用DeleteLocalRef去销毁这个local reference,

    从而导致local reference table中表项不断增加,最后超过最大值,抱出了异常,导致了崩溃。

    举两个例子哈:

    例子1.

    JNIEXPORT jint JNICALL Java_com_example(JNIEnv *env, jobject obj){

      char data[] = "daffdasf";

      int i = 0;

      for(i = 0;i < 1000;i++){

        jstring content = (*env)->NewStringUTF(env, data);

      }

    }

    例子1代码会导致local reference table overflow

    例子2.

    int Java_com_example(char * data){

       JNIEnv *env = NULL;
       JavaVM * vm = NULL;

      vm = getVm();

      (*vm)->AttachCurrentThread(vm, &env, NULL);

         jstring content = (*env)->NewStringUTF(env, data);

    }

    void callExample(){

      int i = 0;

      char data [] = "dafdfdasfds";

      for(i = 0;i < 1000;i++){

        Java_com_example(data);

      }

    }

    例子2代码会导致local reference table overflow

    大家写jni的代码时要防止jni层的内存泄露,要注意用本地语言的方式清除本地语言获得的内存,

    也要注意local reference和global reference的使用。

    当然jni官文文档中没有告诉我们jni层实现的细节,只告诉我们如何规范的编写jni代码,这当然是正确的做法。

    对于使用者来说只需要关注的他的使用不需要关注实现细节,这样就保证了可扩展性。

    所以对于不同的对local reference的实现可能结果不一样,就有可能不出现上面local reference table overflow的错误了。

  • 相关阅读:
    JS数组常用方法参考---5、sort方法
    JS数组常用方法---1、课程介绍
    JS数组常用方法参考---4、unshift方法
    JS数组常用方法参考---3、队列对应的方法
    ES6课程---12、面向对象
    legend3---30、不同类型的网站打包方案
    数据库Sharding的基本思想和切分策略
    用sharding技术来扩展你的数据库(一)sharding 介绍
    什么是Scale Up和Scale Out?
    淘宝网采用什么技术架构来实现网站高负载的
  • 原文地址:https://www.cnblogs.com/lzl-sml/p/3520052.html
Copyright © 2011-2022 走看看