JNI ERROR (app bug): local reference table overflow (max=512)_韩半仙的博客-程序员信息网

      最近在做一个串口协议的jni接口,主要功能就是往串口发送规定协议的命令码,然后异步读取串口返回信息,按照规定协议解析数据,并回调java回调接口,返回解析出来的数据。

      调试的过程中,发现平凡调用接口是会出现以下异常信息:


       看错误信息,应该本地指针块最大只要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; 
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hanmengaidudu/article/details/70554801

智能推荐

Java服务器开发之搭建游戏基础框架_零下三度撸代码的博客-程序员信息网_网游项目程序框架脑图

Java服务器开发之搭建游戏基础框架最开始的项目是一个Maven构建的Java Web项目,使用Tomcat作为Web容器来提供服务。上图是游戏的一个最基础架构的脑图,下面是对应搭建好项目的目录组织下面讲解这基础的项目中最最最重要的一个文件:web.xml文件当启动Web项目会先读取项目中的Web.xml配置文件。 <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welc

FreeRadius客户端基础配置及测试_libinbin_1014的博客-程序员信息网_freeradius客户端

linux系统:centos 6.5FreeRadius客户端: 1.1.7 一、安装freeradius-client-1.1.7.tar.gz下载 wget ftp://ftp.freeradius.org/pub/freeradius/freeradius-client-1.1.7.tar.bz2(有可能会提示找不到文件,我下载时 直接将freeradius-clie

纯css自动全屏轮播图html代码,纯HTML和CSS实现JD轮播图效果_几乎太累了的博客-程序员信息网

使用了纯HTML和CSS实现了JD的轮播图,没有加动态效果,主要是使用了定位的知识。  ,如图为两个侧边箭头图片。LunBo*{padding: 0;margin: 0;}li{list-style: none;}.lunbo{margin: 40px auto;height: 470px;width: 590px;position: relative;}.left,.right{position...

一键查杀linux挖矿脚本,这几个linux命令或许帮您查杀挖矿病毒_weixin_36307344的博客-程序员信息网

最近受类似于比特币及区块链技术的影响,有些云服务器被攻入,植入挖矿病毒,利用你的云服务器来挖矿。本文就阐述几个常用的linux命令,假如你碰到这样的病毒,这些linux命令可能会有些帮助。这些命令并不完全是删除挖矿病毒的一种方面,它们更多的是一种通用的解决问题的方法,不单单局限于挖矿病毒。解决方法本文以这个挖矿进程来举例3798 root 20 0 386m 7852 1272 S...

火电厂烟气排放过程(工况)自动监控解决方案-数据采集网关_Susie酱的博客-程序员信息网

火电厂利用可燃物(例如煤)作为燃料生产电能的工厂。众所周知,可燃物燃烧烟气排放处理不当造成大气污染,严重危害自然环境以及人们身心健康。因此火电厂烟气排放过程自动监控工作必须严格执行。火电厂烟气排放过程(工况)自动监控解决方案火电厂烟气排放过程自动监控解决方案旨在利用环保数采仪组网工况监测系统,对火电厂烟气排放设备运行进行监控、对排放气体污染物因子参数进行采集监测,各数据实时传输至云平台,异常数据警报提示,pc、手机端便捷查询,多中心同步发送,系统管理规范透明化。火电厂烟气排放过程(工况)自动监控解决

随便推点

MATLAB:增加噪声,同时多次叠加噪声图和原图以及求平均图像(imnoise,imadd函数)_早知晓的博客-程序员信息网_怎么把原图和降噪图放在一起matlab

本次涉及了对原图像增加高斯噪声、多次叠加原图和高斯噪声图以及叠加后的平均图像。close all; %关闭当前所有图形窗口,清空工作空间变量,清除工作空间所有变量clear all;clc;RGB=imread('eight.tif'); %读入eight图像,赋值给RGBA=imnoise(RGB,'gaussi...

OAuth2.0授权流程分析_Leon_Jinhai_Sun的博客-程序员信息网_oauth2.0流程解析

Oauth2认证流程第三方认证技术方案最主要是解决认证协议的通用标准 问题,因为要实现 跨系统认证,各系统之间要遵循一定的接口协议。OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时,任何第三方都可以使用OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如PHP、JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间,因而OAUTH是简易的。互联网很多服务如Open API,很多

通过geoserver发布地图瓦片数据_老朱之三十而立的博客-程序员信息网_geoserver发布瓦片地图

最近项目需要离线部署地图服务,中间找了一个合作的公司。现在项目接近尾声,总体感觉合作的公司不成熟,我们自己之前更是没有接触过这种地理信息服务相关的业务,中间也有各种甩锅的经历,这不是重点就不细说了。项目始于Cesium, 中间结合了倾斜模型,模型单体化,离线地图服务部署。今天 主要说一下离线地图服务部署的问题。 地图数据来源 离线地图数据来源,这里需要瓦片数据,一般有好多公司提供下载...

系统配置:Windows系统在Pycharm中配置Git连接Github_Wang_PChao的博客-程序员信息网_pythoncharm怎样连接git

准备工作:安装pycharm 安装git 注册github账户创建SSH Key:如果电脑主目录下没有.ssh文件夹,在git bash中执行如下命令:ssh-keygen -t rsa -C [email protected]将“[email protected]”替换为自己的可用邮箱,注意邮箱两边无引号,否则会出错,例如,在最后验证连接github是否连...

Python Sklearn PCA函数详解_浩浩乎@的博客-程序员信息网_python中pca函数

Python Sklearn PCA函数详解网上看了好多博客,抄来抄去的,都是解释一下皮毛,很多参数的含义和用途都没有说。干脆自己研究一下,有写的不对的地方欢迎指出.官方文档地址 https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html#sklearn.decomposition.PCA...

uni-app 微信小程序 登录状态管理_一kuo米的博客-程序员信息网_uniapp 小程序登录状态

uni-app全局变量实现方式:见文档。 方式多种多样,在这里我只对vuex和uni.setStorageSync进行说明。 方式一 :vuex 1.在项目的根目录下创建文件‘store’,并在‘store’中新建index.js(名称随意起)如下: 说明:可...

推荐文章

热门文章

相关标签