为什么我的 Java 堆转储大小比已用内存小得多? [英] Why is my Java heap dump size much smaller than used memory?

查看:61
本文介绍了为什么我的 Java 堆转储大小比已用内存小得多?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正试图找出我们的 Web 应用程序中大量内存泄漏的罪魁祸首.我们在查找内存泄漏方面的经验非常有限,但我们发现了如何使用 jmap 进行 java 堆转储并在 Eclipse MAT 中对其进行分析.

We are trying to find the culprit of a big memory leak in our web application. We have pretty limited experience with finding a memory leak, but we found out how to make a java heap dump using jmap and analyze it in Eclipse MAT.

但是,由于我们的应用程序使用 56/60GB 内存,堆转储的大小仅为 16GB,在 Eclipse MAT 中甚至更少.

However, with our application using 56/60GB memory, the heap dump is only 16GB in size and is even less in Eclipse MAT.

我们的服务器在 Ubuntu 14.04 上使用 Wildfly 8.2.0 作为我们的 java 应用程序,其进程使用了​​ 95% 的可用内存.进行转储时,我们的缓冲区/缓存使用空间为 56GB.

Our server uses Wildfly 8.2.0 on Ubuntu 14.04 for our java application, whose process uses 95% of the available memory. When making the dump, our buffers/cache used space was at 56GB.

我们使用以下命令创建转储:sudo -u {application user} jmap -dump:file=/mnt/heapdump/dump_prd.bin {pid}

We used the following command to create the dump: sudo -u {application user} jmap -dump:file=/mnt/heapdump/dump_prd.bin {pid}

堆转储文件大小为 16.4GB,当使用 Eclipse MAT 对其进行分析时,它说有大约 1GB 的活动对象和约 14.8GB 的​​不可达/浅堆.

The heap dump file size is 16,4GB and when analyzing it with Eclipse MAT, it says there are around 1GB live objects and ~14,8GB unreachable/shallow heap.

以下是有关我们所看到的问题的更多信息.我们监控我们的内存使用情况,我们看到它不断增长,直到剩下大约 300 mb 的可用内存.然后它保持在那个内存量附近,直到进程崩溃,不幸的是应用程序日志中没有错误.

Here is some more info about the problem we see happening. We monitor our memory usage, and we see it grow and grow, until there is ~300mb free memory left. Then it stays around that amount of memory, until the process crashes, unfortunately without error in the application log.

这让我们假设这是一个硬 OOM 错误,因为这只会在内存接近耗尽时发生.我们为 JVM 使用设置 -Xms25000m -Xmx40000m.

This makes us assume it is a hard OOM error because this only happens when the memory is near-depleted. We use the settings -Xms25000m -Xmx40000m for our JVM.

基本上,我们想知道为什么我们的大部分内存没有在这个转储中被捕获.顶部保留的大小类看起来不太可疑,所以我们想知道是否有一些与堆转储相关的东西我们做错了什么.

Basically, we are wondering why the majority of our memory isn't captured in this dump. The top retained size classes don't look too suspicious, so we are wondering if there is something heap dump-related what we are doing wrong.

推荐答案

在转储其堆时,JVM 将首先运行一个垃圾回收周期以释放任何无法访问的对象.

When dumping its heap, the JVM will first run a garbage collection cycle to free any unreachable objects.

如何我可以在不先收集垃圾的情况下在 Java 5 上进行堆转储吗?

根据我的经验,在真正的 OutOfMemoryError 中,您的应用程序只是要求比可用堆空间更多的堆空间,这个 GC 是一个傻瓜的差事,最终的堆转储将是最大的大小.堆大小.

In my experience, in a true OutOfMemoryError where your application is simply demanding more heap space than is available, this GC is a fool's errand and the final heap dump will be the size of the max. heap size.

当堆转储非常小时,这意味着系统并不是真的内存不足,而是可能有内存压力.例如,有 java.lang.OutOfMemoryError: GC 开销限制超出 错误,这意味着 JVM 可能已经能够释放足够的内存来服务一些新的分配请求,但它不得不花费收集垃圾的时间太多了.

When the heap dump is much smaller, that means the system was not truly out of memory, but perhaps had memory pressure. For example, there is the java.lang.OutOfMemoryError: GC overhead limit exceeded error, which means that the JVM may have been able to free enough memory to service some new allocation request, but it had to spend too much time collecting garbage.

也有可能你没有内存问题.是什么让你觉得你在做什么?您没有提到有关堆使用或 OutOfMemoryError 的任何内容.您只提到了 JVM 在操作系统上的内存占用.

It's also possible that you don't have a memory problem. What makes you think you do? You didn't mention anything about heap usage or an OutOfMemoryError. You've only mentioned the JVM's memory footprint on the operating system.

这篇关于为什么我的 Java 堆转储大小比已用内存小得多?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆