JNI ERROR (app bug): local reference table overflow (max=512)

简介: JNI ERROR (app bug): local reference table overflow (max=512)

应用报未知错误



应用安装好连接电脑就能看错误信息


一般会是so库问题


怎么解决:so升级,so打包时间过老,不适合现在的种种环境,上网上搜索。


image.png


image.png


JNI ERROR (app bug): local reference table overflow (max=512)



看错误信息,应该本地指针块最大只要512个,当平凡调用之后,可能越界了,超出了范围,导致异常。


当线程从 Java 环境切换到 native code 上下文时(J2N),JVM 会分配一块内存,创建一个 Local Reference 表,这个表用来存放本次 native method 执行中创建的所有的 Local Reference。每当在 native code 中引用到一个 Java 对象时,JVM 就会在这个表中创建一个 Local Reference。比如我们调用 NewStringUTF() 在 Java Heap 中创建一个 String 对象后,在 Local Reference 表中就会相应新增一个 Local Reference。运行 nativemethod 的线程的堆栈记录着 Local Reference 表的内存位置,Local Reference 表中存放 JNI Local Reference,实现 Local Reference 到 Java 对象的映射。native method 代码间接访问 Java 对象。通过线程堆栈中的记录着 Local Reference 表的内存位置的指针定位相应的 Local Reference 的位置,然后通过相应的 Local Reference 映射到 Java 对象。


当 nativemethod 引用一个 Java 对象时,会在 Local Reference 表中创建一个新 Local Reference。在 Local Reference 结构中写入内容,实现 Local Reference 到 Java 对象的映射。


native method 调用 DeleteLocalRef() 释放某个 JNI Local Reference 时,首先通过线程堆栈中的记录着 Local Reference 表的内存位置的指针定位相应的 Local Reference 在 Local Ref 表中的位置,然后从 Local Ref 表中删除该 Local Reference,也就取消了对相应 Java 对象的引用(Ref count 减 1)。


当越来越多的 LocalReference 被创建,这些 Local Reference 会在 Local Ref 表中占据越来越多内存。当 Local Reference 太多以至于 Local Ref 表的空间被用光,JVM 会抛出异常,从而导致 JVM 的崩溃。

 

产生Local Reference的操作有:


1.FindClass

2.NewString/ NewStringUTF/NewObject/NewByteArray

3.GetObjectField/GetObjectClass/GetObjectArrayElement

4.GetByteArrayElements和GetStringUTFChars

 

解决方法:


在native method中引用完java对象后及时调用env->DeleteLocalRef方法手动释放本地引用


如果native method返回java对象就不需要手动release,因为java会自动回收

但通过JNI传递对象数组时,由于需要在一个for循环中将C++对象数组成员中的每一个元素通过SetObjectField与java对象的元素进行对应,并调用SetObjectArrayElement将对象添加到数组中,期间可能会不断生成local reference,但是不能在循环中手动release,最终引起local reference内存泄露,因此针对与这种情况可以将对象数组分批传递

 

举例如下:  

 

1、当java和c回调传的参数过多的时候,会出现内存泄露问题, 列如程序运行一段时间之后,莫名的出现如下错误JNI ERROR (app bug): local reference table overflow (max=512) Failed adding to JNI local ref table (has 512 entries) VM aborting  

 

2、 引起这个bug的原因有如下几个:

 

上层传递参数String 给下层C语言,当底层使用完数据之后,一定要掉用ReleaseStringUTFChars接口将内存释放掉,不然当传递次数多了之后会导致系统奔溃


JNIEXPORT jint JNICALL test_string(JNIEnv *env, jobject obj,jstring j_usrname,jstring j_passwd,jint j_host_id) 
{  
int usr_id =1; 
const char *usrname =  env->GetStringUTFChars (j_usrname, NULL);  LOGD("usrname = %s",usrname); 
env->ReleaseStringUTFChars (j_usrname, usrname);  
return 1; 
}


3、底层jni里面C语言接口调用上层java的方法时候,一定要释放obj类,不然也会导致系统奔溃,如下列子:

底层子线程当中要调用上层的java的方法  


3.1在cpp接口程序里面定义全局变量 JavaVM *g_jvm=NULL; jobject g_obj = NULL;

3.2在创建线程函数之前,给这两个变量赋值


JNIEXPORT jint JNICALL init(JNIEnv *env, jobject obj,jint mode) 
{    
env->GetJavaVM(&g_jvm); 
g_obj = env->NewGlobalRef(obj);    pthread_t tid; 
pthread_create(&tid,NULL,testjni,NULL); 
}


3.3在线程函数里面调用上层的一个void fun(int a);方法  (注:只要在jni底层,除了自己用onload映射出来接口相对于整个APP来说是主线程函数以外,其它c函数接口都视为子线程函数)


void *testjni(void *arg) 
{  
    JNIEnv *env;  
    jmethodID met;  
    jclass cls;  
    while(1)  
   { 
        if(g_jvm->AttachCurrentThread(&env, NULL) != JNI_OK)
       {    
           LOGD("%s: AttachCurrentThread() failed", __FUNCTION__);    
           return NULL; 
       } 
       cls = env->GetObjectClass(g_obj); 
       met =env->GetMethodID(cls, "fun","(I)V");   
       env->CallVoidMethod(g_obj, met, 10); 
       env->DeleteLocalRef(g_obj);  //注意必须释放缓存数据   sleep(1); 
    } 
    return NULL; 
}


目录
相关文章
|
8月前
|
移动开发
钉钉H5微应用配置IP,应用首页地址报错:app url exceeds max length limit,这个怎么处理?
钉钉H5微应用配置IP,应用首页地址报错:app url exceeds max length limit,这个怎么处理?
667 0
|
8月前
Error:Execution failed for task ':app:processDebugManifest'. > Manifest merger failed with multiple
Error:Execution failed for task ':app:processDebugManifest'. > Manifest merger failed with multiple
52 1
|
4月前
|
监控 JavaScript 前端开发
深入理解 Nuxt.js 中的 app:error 钩子
【9月更文挑战第25天】在 Nuxt.js 中,`app:error` 钩子是一个强大的工具,用于处理应用程序中的各种错误。它可以在服务器端渲染或客户端运行时触发,帮助提升应用稳定性和用户体验。通过在 `nuxt.config.js` 中定义该钩子,开发者可以实现错误页面显示、错误日志记录及错误恢复等功能,确保应用在遇到问题时能妥善处理并恢复正常运行。
58 10
|
5月前
|
IDE 网络安全 开发工具
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
|
4月前
|
开发者 UED
深入理解 Nuxt.js 中的 app:error 钩子
【9月更文挑战第26天】在 Nuxt.js 中,钩子函数是在特定生命周期阶段执行代码的机制,`app:error` 钩子用于处理应用中的错误,包括服务器端和客户端渲染时出现的问题。它提供了一个集中处理错误的机制,提升了用户体验。当组件渲染过程中出现错误时,`app:error` 钩子会被触发,可以在 `nuxt.config.js` 文件中定义该钩子。通过分析错误对象 `err` 和上下文信息 `context`,开发者可以更好地处理各种错误情况。相比组件内的 `try/catch` 或浏览器原生错误处理,`app:error` 提供了更全局和有针对性的错误处理方式。
|
5月前
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
|
5月前
|
C#
【Azure Function】Function App启动时出现 Failed to open local port 4001 错误,这是什么情况呢?
【Azure Function】Function App启动时出现 Failed to open local port 4001 错误,这是什么情况呢?
|
5月前
|
Java Linux Shell
【Azure 应用服务】部署Jar到App Service for Linux,因启动命令路径配置错误而引起:( Application Error 问题
【Azure 应用服务】部署Jar到App Service for Linux,因启动命令路径配置错误而引起:( Application Error 问题
|
5月前
|
Linux C#
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
【Azure App Service】C#下制作的网站,所有网页本地测试运行无误,发布至Azure之后,包含CHART(图表)的网页打开报错,错误消息为 Runtime Error: Server Error in '/' Application
|
5月前
|
JavaScript Linux Windows
【应用服务 App Service】NodeJS +Egg 发布到App Service时遇见 [ERR_SYSTEM_ERROR]: A system error occurred:uv_os_get_passwd returned ENOENT(no such file or directory)
【应用服务 App Service】NodeJS +Egg 发布到App Service时遇见 [ERR_SYSTEM_ERROR]: A system error occurred:uv_os_get_passwd returned ENOENT(no such file or directory)
111 0