Local Reference Overflow

概述

有幸碰到过这样一个错误:JNI ERROR (app bug): local reference table overflow (max=512)

错误的意思是JVM的局部引用表溢出了。局部引用表的作用是在Native方法返回前,保存局部引用,一旦其返回,则将局部引用表中的对象回收。简单理解,即为垃圾回收服务的。

如何获取一个局部引用呢?有两种方法:
1. 通过NewLocalRef创建一个局部引用;
2. 引用一个Java对象,如引用CallStaticObjectMethod返回的对象

如何释放呢?有两种方法:
1. 通过DeleteLocalRef
2. 等Native方法返回

重现

要重现这个问题,很简单,在Native方法中NewLocalRef 512次即可。

常见的Native方法调用,调用方向是Java -> c/c++ -> Java,也就是Java代码调用了一个Native方法,做了某件事,然后返回Java继续执行。这一调用过程局部引用表将在Native调用结束时会自动回收。

然而,要特别注意的是另一种形式的Native方法。也是最容易出现local reference table overflow的。调用方向是Java -> c/c++ -> thread -> callback Java,也就是Native方法起了一个线程,后台做某件事情,但又需要Java方法提供一些信息。

注意callback Java,这里如果是CallStaticObjectMethod之类的方法,将引用Java对象,占用一格局部引用表。但什么时候Native方法返回,并回收局部引用表呢?要到线程执行结束,或者说DetachCurrentThread之后。而一般后台线程的运行时间较长,不断地引用Java对象而没有及时回收,很容易触发该bug。

解决

最可靠的解决方法是及时回收(即DeleteLocalRef

对于回调Java方法的后台线程,另一解决方法是,仅在必要时attach线程,并及时detach线程

参考

以下是来自Android developer网站的解释

One unusual case deserves separate mention. If you attach a native thread with AttachCurrentThread, the code you are running will never automatically free local references until the thread detaches. Any local references you create will have to be deleted manually. In general, any native code that creates local references in a loop probably needs to do some manual deletion

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值