安卓ZXing库是否存在内存泄漏问题?

4
我使用ZXing库编写了一个Android应用程序,出现了java.lang.OutOfMemoryError错误。
起初,我确信错误是在我这边,所以根据Patrick Dubroy(见Google I/O 2011: Memory management for Android Apps和其他教程)的建议,使用Eclipse Memory Analyzer(MAT)来查找内存泄漏,如Android Memory Leaks OR Different Ways to Leak
在MAT中,我发现随着时间的推移,数百个com.google.zxing.common.BitMatrix实例占用了大部分堆内存。
令人惊讶的是,我在原始的ZXing测试程序“CaptureActivity”中也遇到了同样的问题!
经过一些调查,我有一个线索,即DecodeHandler类中的活动引用可能会阻止垃圾收集器释放BitMatrix。但我经验不足,无法验证这一点。此外,我很惊讶在原始的ZXing库(版本2.1)中发现了这个问题。
是否有人可以重现这种现象或曾经遇到过类似情况?

1
我从未看到内存泄漏的证据,也想不到可能会有引用被保存的地方。它们被引用的位置在哪里显示? - Sean Owen
这与这个问题有什么关系? - Sean Owen
2个回答

0

我认为你走在了正确的道路上。你需要继续研究MAT堆剖面,以确定用户代码的哪一部分持有对DecodeHandler和传递到BitMatrix的引用。尝试跟踪BitMatric的入站引用,计算支配树并检查泄漏嫌疑。

尝试对应用程序进行分析,看看哪一部分代码负责BitMatrix的分配,并尝试将其追溯回应用程序代码。

捕获活动示例遇到相同问题的事实可能是由于错误使用库造成的,因此这并不一定证明该库存在内存泄漏。例如,库可能已更新,而示例仍然保持不变。


0
我在 Android 模拟器(Intel 版本)上运行时发现了与 ZXing 2.3 版本相同的问题。根本原因似乎是以下内容: 在类 FinderPatternFinder 的方法 selectBestPatterns 中,如果未找到有效的(QR)查找器模式,则会抛出 NotFoundException 异常。在类 MultiFormatReader 的方法 decodeInternal 中捕获此异常。因此,此异常跳过了一些方法调用的正常返回。我发现由于这种“异常返回”,FinderPatternFinder 实例没有被释放,而该实例反过来又持有 BitMatrix 的引用,BitMatrix 使用了相当多的内存。 听起来很疯狂,我认为这不符合 Java 规范,所以我称它为模拟器中的一个错误。 解决方法是不要依赖异常来表示未找到查找器模式。我通过在方法调用堆栈中逐步返回一些 null 结果来解决了这个内存泄漏问题。这完全解决了内存泄漏问题。

如果是真的,那确实是JVM实现中的一个bug。控制流完全正常,与垃圾回收无关。这些元素离开了帧栈;你认为它们被保存在哪里?如果这些都是真的,更有可能的是模拟的JVM GC跟不上帧的处理速度,因为它的线程花费的时间太长而宣布OOM。 - Sean Owen
@SeanOwen:模拟的JVM非常快,因为它在快速虚拟模式下运行Intel代码。我使用MAT找到了堆栈之外的元素所占用的内存。它显示了这些元素,但没有显示它们所依附的对象。你可以在LogCat中看到使用的内存不断增长,直到达到限制。 - Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接