繁体   English   中英

如何在堆转储中的异常实例没有入站引用的情况下调试内存泄漏?

[英]How to debug memory leak where exception instances in heap dump have no inbound references?

我一直在尝试诊断我正在编写的Android应用程序中的内存泄漏。 我有一个堆转储加载到Eclipse中,但我看到的结果非常好奇。 堆中有大约20,000个异常实例(特别是来自UnboundID LDAP库的LDAPException),没有入站引用。

也就是说,它们出现在支配者树的根部。 OQL SELECT objects e FROM com.unboundid.ldap.sdk.LDAPException e WHERE (inbounds(e).length = 0)返回超过20,000个结果,总计几乎所有堆。 然而,GC在堆转储之前运行,我可以看到它在执行泄漏代码期间反复运行在控制台中。 如果这些实例没有入站参考,那么可以让它们保持活力?

我也尝试过“最短的GC路径”查询。 它显示了一个保留2个实例的LDAPConnectionReader行,以及具有各种十六进制地址的~20k LDAPException @ <addr> unknown行。

更新 :自发布以来我没有时间进一步诊断这个问题,我发布的奖金在我可能会结束之前结束。 我现在尽可能地奖励它,以免浪费点数。 感谢所有关注此事的人! 我将稍后回来并再次更新进一步诊断的结果,当生活稍微忙碌时。

无论这些异常是否被抛出,就内存使用而言,这个细节都是无关紧要的。

虽然您希望在堆转储中看到谁拥有引用,但由于某种原因,您无法实现此目的。 我想知道本机代码是否会在堆转储工具中得到正确的符号化?

无论哪种方式,作为尝试的新事物,我建议不要调试抛出这些异常但创建它们的位置。 在类和/或其所有构造函数上放置断点。 理想情况下,您只是从堆转储引用中获取此信息,但如果您可以看到谁重复构建这些对象,它仍然可以证明是有用的......我猜它们来自同一个地方。

如果您使用的是Eclipse,则可以在LDAPException上添加断点。 在这里,您可以找到有关如何设置一个的教程: Eclipse提示:异常断点

只要抛出所选类型的异常,这些断点就会暂停执行。 一旦找到引发如此多异常的条件,就可以修复bug。

它并没有完全调试为什么未引用的异常填满堆,但我希望它可以帮助。

我不熟悉OQL,特别是Android平台,或者该平台上Java GC的内部工作原理,但对我来说最明显的是缺少的LDAPException元数据。 它有错误代码,消息,方法等......它在哪里? 这是未初始化的吗? 你有没有发布所有这些东西? 像服务器重定向到自身的东西可能让我说“哦,这很奇怪,但它有点意义。”

您是否尝试过将此lib替换为JDK 看起来如果可能的话应该很容易。

然后我会开始挤压它所有的东西。 GC特征可以提供线索。 是否存在以某种方式逃避收集的实例? 每秒创建多少? 每次通过gc'd会有多少陈旧的,或者它是不变的? 他们是在像Danny谈论的忙碌循环中创建的吗? 如果你在繁忙的循环中调用System.gc()怎么办?

但是,是的,我开始打印调试。 希望有更好的解决方案。 :-P

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM