如何在Java/Android中查找内存泄漏

如何在Java/Android中查找内存泄漏,java,android,kotlin,memory-leaks,Java,Android,Kotlin,Memory Leaks,我在我们的一个应用程序中遇到了很多内存泄漏的问题,不知道下一步该怎么办。我知道有人问过类似的问题,但没有人给出任何有用的答案 当我们在androidstudio中使用profiler时,它显示“本机”内存增长相当快,在使用该应用程序大约10-15分钟后,它将因内存泄漏而崩溃 我们的应用程序完全是用java和kotlin编写的,我已经查找了所有静态对象,或者是保存在垃圾收集器可能无法收集的伴生对象中的对象,但是除了一些用于日志记录的静态字符串(如标记) 我们尝试使用泄漏金丝雀,但它似乎找不到任何内

我在我们的一个应用程序中遇到了很多内存泄漏的问题,不知道下一步该怎么办。我知道有人问过类似的问题,但没有人给出任何有用的答案

当我们在androidstudio中使用profiler时,它显示“本机”内存增长相当快,在使用该应用程序大约10-15分钟后,它将因内存泄漏而崩溃

我们的应用程序完全是用java和kotlin编写的,我已经查找了所有静态对象,或者是保存在垃圾收集器可能无法收集的伴生对象中的对象,但是除了一些用于日志记录的静态字符串(如
标记

我们尝试使用泄漏金丝雀,但它似乎找不到任何内存泄漏,并不断告诉我们我们的应用程序是好的。我甚至故意添加了一个漏洞,通过静态地保持android活动上下文,以确保漏洞金丝雀能够正常工作,而事实确实如此


是否还有其他可能导致java代码内存泄漏的因素需要注意?我可能持有的任何特定对象都会导致这种情况?

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

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

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

谢谢,我一直在使用探查器来完成此操作,但运气不好。我发现所有增加的内存都属于“本机”类别,似乎字节[]和字符串是占用最大大小的两个对象…@ThomasCook我可以很容易地复制它,我会尝试查看调用堆栈,看看我在探查器中找到了什么。。。我想你刚刚给了我一个可能是什么的想法,所以我希望我的怀疑是正确的,会在一点后更新。@ThomasCook不是真的,也许,我不确定。。。我们发现,似乎正在填充内存的对象是byte[],并且它似乎指向一个特定的byte[],该byte[]被作为一个方法的参数,该方法将递归地调用自身以分块解析byte[]。但是这个方法中的字节[]不是静态的或全局的,所以我不确定为什么在方法完成后它不会被垃圾收集。(该方法最终会完成)。。。但我认为我们已经把它缩小到可能与该方法有关的程度。@ThomasCook我们都使用这两种方法,尽管我怀疑的递归方法是用Java实现的。我有一些其他的东西要先尝试,但如果不成功,那么我可能会将文件转换为kotlin,然后尝试你的建议。这个函数有点大,充满了一堆意大利面代码,调用了许多其他函数,然后调用递归函数。。。所以发布它的最小版本将是一项工作。尽管我可能会尝试一下,如果我在这个问题上坚持很久的话:波赫,我明白了,哈哈,在这种情况下,你有两个问题,还有一道相当美味的菜(意大利面+递归):P@ThomasCook问题已经解决了!结果根本不是内存问题。崩溃会说
OutOfMemory
,所以我们假设是这样,但后来我发现一条日志消息说
pthread\u create failed
,我想,嗯,这很奇怪,我们的CPU使用情况是什么样子的。。。我们有超过4000个线程!!!结果表明,递归方法正在旋转一组线程(这会快速增加我们的内存),而没有一个线程退出。将它切换为使用线程池,而不是仅仅旋转一个新线程,所有问题都得到了解决。