Java Heap dump:如何通过1.io.netty.Buffer.ByteBufUtil 2.byte[]数组查找占用内存的对象/类
我发现我的一个Spring Boot项目的内存(RAM消耗)每天都在增加。当我将JAR文件上传到AWS服务器时,它占用了582MB的RAM(最大分配的RAM是1500MB),但是每天的RAM都在增加50MB到100MB,5天后的今天,它占用了835MB。目前项目用户规模为100-150人,睡觉API使用正常。
由于RAM的增加,应用程序多次关闭,并出现以下错误(从日志中发现错误):
Exception in thread "http-nio-3384-ClientPoller" java.lang.OutOfMemoryError: Java heap space
因此,为了解决这个问题,我发现通过使用Java Heap转储,我可以找到占用内存的对象/类。因此,通过在命令行中使用Jmap
,我已经创建了一个堆转储,并将其上传到Heap Hero和Eclipse Memory Analyzer Tool。在这两个文件中,我发现了以下内容:
1.总浪费内存为:64.69MB(73%)(查看下面的截图)
2。其中34.06MB被Byte [] array
和LinkedHashmap[]
占用(请查看下面的截图),这是我在整个项目中从未使用过的。我在我的项目中搜索了它,但没有找到。
3。以下两个大对象分别占用32MB和20MB。
1. Java Static io.netty.buffer.ByteBufUtil.DEFAULT_ALLOCATOR
2. Java Static com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.connectionFinalizerPhantomRefs`
所以我试图找到这个netty.buffer。在我的项目中,但我找不到任何与netty或Buffer匹配的内容。
现在我的问题是如何减少此内存泄漏或如何找到确切的内存消耗对象/类/变量以便减小堆大小。
我知道很少有专家会要求提供源代码或类似的东西,但我相信从堆转储中可以找到内存中可用的内存泄漏或活动对象。我正在寻找该选项或任何可以减少此堆转储的选项!
我在过去的3周里一直在处理这个问题。任何帮助都将不胜感激。 谢谢!
解决方案
首先启用JVM native memory tracker,通过添加标志-XX:NativeMemoryTracking=summary
了解内存的哪个部分在增加。根据文档,存在一些性能开销(5-10%),但如果这不是问题,我建议即使在生产中也启用此标志来运行JVM。
然后您可以使用jcmd <PID> VM.native_memory
检查这些值(此答案中有一个很好的记录:Java native memory usage)
如果确实分配了很大的本机内存块,则很可能是由Netty分配的。
您如何在AWS中运行您的应用程序?如果它在Docker映像中运行,您可能会遇到这个问题:What would cause a java process to greatly exceed the Xmx or Xss limit? 在这种情况下,如果您的应用程序使用本机内存(Netty就是这样)并在具有大量内核的服务器上运行,则可能需要设置环境变量MALLOC_ARENA_MAX
。完全有可能的是,JVM为Netty分配了这个内存,但是没有看到任何释放它的理由,因此它看起来只会继续增长。
如果您想控制Netty可以分配多少本机内存,您可以为此使用JVM标志-XX:MaxDirectMemorySize
(我相信默认值与Xmx
相同),并在您的应用程序不需要那么多内存的情况下降低它。
JVM内存调优是一个复杂的过程,当涉及到本机内存时,它会变得更加复杂-正如链接的答案所示,它不像简单地设置Xms
和Xmx
标志并期望不再使用内存那么简单。
相关文章