java - 为什么我的 Java 堆转储大小比使用的内存小得多?

标签 java memory-leaks heap-memory heap-dump jmap

问题

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

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

上下文

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

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

堆转储文件大小为 16.4GB,当使用 Eclipse MAT 对其进行分析时,它表示有大约 1GB 的 Activity 对象和约 14.8GB 的​​不可访问/浅堆。

编辑:这里有一些关于我们看到的问题的更多信息。我们监控我们的内存使用情况,我们看到它越来越大,直到剩下大约 300mb 的可用内存。然后它停留在那个内存量附近,直到进程崩溃,不幸的是应用程序日志中没有错误。

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

问题

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

最佳答案

当转储其堆时,JVM 将首先运行垃圾回收周期以释放所有无法访问的对象。

How can I take a heap dump on Java 5 without garbage collecting first?

根据我的经验,在真正的 OutOfMemoryError 中,您的应用程序只是要求比可用空间更多的堆空间,此 GC 是徒劳的,最终的堆转储将是最大值的大小。堆大小。

当堆转储小得多时,这意味着系统并非真正内存不足,而是可能存在内存压力。例如,存在 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误,这意味着 JVM 可能已经能够释放足够的内存来处理一些新的分配请求,但它不得不花费收集垃圾的时间太多了。

也有可能您没有内存问题。是什么让你认为你这样做?您没有提及有关堆使用情况或 OutOfMemoryError 的任何内容。您只提到了 JVM 在操作系统上的内存占用。

关于java - 为什么我的 Java 堆转储大小比使用的内存小得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32271731/

相关文章:

C++ Opengl,Win内存泄漏

parsing - Haskell 的 parsec 中 CPS 与非 CPS 解析器的堆使用情况

java - 如何更改 smart gwt 中 vPanel 的成员

javascript - 在 Firefox 中使用 window.eval() 内存泄漏?

java - 在 Swing 中使用 setBounds() 的缺点

tomcat - 无法取消部署 Tomcat 7 中的 Web 应用程序

C 堆栈分配大小

c# - 缓冲区是从共享堆中为大小为 64 KB 的进程分配的?

javascript - Selenium - 元素不可见错误 - 周期性发生

java - 增强的for语句