【问题标题】:How to find a memory leak in Java / Android如何在 Java / Android 中查找内存泄漏
【发布时间】:2020-01-17 14:38:06
【问题描述】:

我在我们的一个应用程序中遇到了很多内存泄漏问题,不知道下一步该往哪里看。我知道有人问过类似的问题,但没有一个有帮助的答案。

当我们在 android studio 中使用分析器时,它显示“本机”内存增加得非常快,并且在使用该应用大约 10-15 分钟后,它会因内存泄漏而崩溃。

我们的应用程序完全用 java 和 kotlin 编写,我已经查看了所有静态对象,或者保存在伴随对象中的对象,这些对象可能不会被垃圾收集器收集,但除了一些静态字符串之外别无他物TAG 用于记录。

我们尝试使用泄漏金丝雀,但它似乎找不到任何内存泄漏并一直告诉我们我们的应用程序很好。我什至故意通过静态保持一个 android 活动上下文来添加泄漏,只是为了确保泄漏金丝雀正在工作,而且确实如此。

还有其他我应该注意的可能导致我的 java 代码中的内存泄漏的事情吗?我可能持有的任何特定对象导致此问题?

【问题讨论】:

  • @ThomasCook 我可以轻松复制它,我会尝试查看调用堆栈,看看我在分析器中找到了什么......我想你只是让我知道它可能是什么所以我希望我的猜测是正确的,稍后会更新。
  • @ThomasCook 不是真的,也许,我不确定......我们发现填充内存的对象似乎是字节[],它似乎指向特定的字节[] 作为一个方法的参数,该方法将递归调用自身以分块解析 byte[]。但是这个方法中的 byte[] 不是静态的或全局的,所以我不确定为什么在方法完成后它不会被垃圾收集。 (该方法最终会完成)...但我认为我们已将其范围缩小到可能与该方法有关。
  • @ThomasCook 我们两者都使用,尽管我怀疑的递归方法是在 Java 中。我还有其他几件事要先尝试,但如果不成功,那么也许我会将文件转换为 kotlin 并尝试您的建议。该函数有点庞大,充满了一堆意大利面条代码,调用许多其他函数,然后调用递归函数......所以发布它的最小版本将是一些工作。虽然如果我坚持这么久,我可能会试一试:P
  • 哦,我明白了哈哈,在那种情况下,你有 2 个问题,还有一道相当美味的菜(意大利面 + 递归):P
  • @ThomasCook 问题已解决!它最终根本不是内存问题。崩溃会说OutOfMemory,所以我们认为它是,但后来我发现一条日志消息说pthread_create failed,我想,嗯,这很奇怪我们的CPU使用率是什么样的......我们有超过4000个线程!!!结果证明递归方法正在启动一堆线程(这正在迅速增加我们的内存)并且没有一个线程退出。将其切换为使用线程池,而不是仅仅启动一个新线程,所有问题都解决了。

标签: java android kotlin memory-leaks


【解决方案1】:

在 Android Studio 中,您可以通过按下 Dump Java heap 按钮来生成堆转储:

在这里你可以看到哪个类使用了多少内存。例如,您可能会发现一个本应由垃圾收集器收集但没有收集的类。

**更新: 正如您所说,问题在于本机内存分配,但我会保留这个答案,因为它可能对其他人有帮助。

【讨论】:

  • 谢谢,我一直在使用分析器来执行此操作,但没有任何运气。我发现所有增加的内存都属于“本机”类别,似乎 byte[] 和 String 是占用最大大小的两个对象......
猜你喜欢
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 2011-01-09
相关资源
最近更新 更多