为什么JNI Global引用具有最大数量限制?

时间:2017-07-29 03:29:58

标签: android java-native-interface

众所周知,JNI是Java和C ++之间的桥梁。最近我正在为Java项目编写代码,它的主要模块基于C ++,需要存储大量的GlobalReference。它会随着活动的开放而增加。因此GlobalReferences的最大数量(65535)成为严重问题,我必须使用特殊方法解决问题。

所以我对GlobalReferences的限制感兴趣。 它仅用于检测内存泄漏as other's saying吗?

3 个答案:

答案 0 :(得分:2)

很容易回答'为什么' 这个问题。 Android JVM中的全局参考表(无论是Dalvik还是ART)的条目数量有限,因为它的架构师并不认为有人需要更多。

他们担心有不同的限制:内存限制,性能,稳定性,维护工作。

但毕竟,这更像是一个修辞问题,而答案却不如实际建议那么重要。以下是:

  • Android JVM中对引用表的限制仍然存在。不要期望这些表格会在下一个Android版本中变得更大(但可能会有一些)

  • 无论Android的未来版本发生什么,目前的版本都将保留。数百万人still using Android devices with Gingerbread,于2010年发布(占20亿的0.6%)。截至today,超过20%的人在其设备上安装了Dalvik JVM。

  • 如果达到或接近内部JVM表的限制,则必须重新考虑您的体系结构。当这些表溢出时,您无法信任系统的行为,即使每次都不会发生这种情况。

  • 请记住,您的应用程序可用的内存也是有限的,您使用的越多,您的应用程序在多任务环境中遭受性能损失的可能性就越大:如果内核需要其他应用程序的内存,内核可以随时终止它

  • 如果在Java端聚合对象,则可以避免表溢出。例如。您可以将它们放在Java映射或数组中,而不是保留对数千个对象的全局引用,并在C ++中保留对该集合的全局引用。您可以使用JNI在C ++中管理集合,以访问Map.put()Map.remove

答案 1 :(得分:1)

根据我的理解,它不是真正检测内存泄漏,而是关于完全管理内存。 (至于内存泄漏,很明显,你不得不在本机代码中挂起Java对象的时间比你需要的时间长,全局引用与否)全局引用的使用在某种程度上是反模式(当用于解决问题时)可以用其他方法解决大多数语言,afaik。

与JNI的关系是您的本机代码处于从属模式,所以说。 JVM无法清除您在C代码中保留的内容,尤其是全局引用(因为它们的生命周期是无限期的),因此这些限制是防止开发人员滥用JNI并在脚下射击的措施

另外,我有点好奇你要完成的任务,你必须存储超过65k的全球参考资料 - 我感觉你正在努力完成的任务允许一种不同的方法,一种不会使JNI超越边缘的方法。

E.g。现在我将原生数据库库连接到Android应用程序,整个设置必须来回丢弃数十万个db记录,即使这个案例也有一个解决方案,即使是本地参考也不会溢出table(512 ref limit)更不用说全局ref表了。

我知道这可能已经很晚了,但是如果你愿意分享你的实际任务,我们或许能够找到一个正确的方法来处理它。

答案 2 :(得分:1)

此限制有一个明显的解决方法,我现在也必须使用。只需声明一个对象数组并在该数组中使用索引即可。

在矢量程序中优先使用数组,因为Java程序中的间接级别已经很高。您可以通过几行琐碎的代码自己在数组中分配更大的数量和经理可用的插槽。