堆转储!=虚拟内存?

时间:2015-09-25 10:29:51

标签: java memory jenkins dump heap-dump

不是真正了解Java,特别是关于Java的调试,但是使用Monitoring在Jenkins中进行堆转储,然后使用MAT在Eclipse中对其进行解码,显示总内存使用了169.4 MB,而在Jenkins监控内存似乎经常被大量使用并且GC经常运行。 -XmX是4G。

为什么我只用MAT获得169.4 MB?可能是因为在进行转储之前Jenkins执行GC吗?如果是这样,我可以避免它看到完整的内存转储吗?

3 个答案:

答案 0 :(得分:3)

了解记忆

是的,Java堆转储和虚拟内存转储(在Windows上称为“崩溃转储”或“内存转储”)是不同的。

Java堆转储仅包含与Java相关的内存,即Java对象所在的位置。使用MAT(如您所述)或Java Heap Analysis Tool

等工具分析Java堆转储

(用户模式)进程的Windows崩溃转储包含所有虚拟内存,其中虚拟内存是提供内存的操作系统的术语。在Windows上,这是通过VirtualAlloc分配的所有内存。

操作系统虚拟内存将包含 Java堆,因为Java只能从操作系统请求内存。

因此,在比较内存大小时,了解该工具是特定于Java还是OS一般非常重要。

在您的情况下, Monitoring 看起来很像通用工具,因为它处理进程列表和CPU时间,没有任何看似Java特定的东西。另一方面, MAT 显然是一个Java工具。

记忆差异

那么Java堆大小与虚拟内存大小有多大差异?

大部分:

  1. 加载的EXE / DLL帐户到虚拟内存,但不到Java堆
  2. 本机代码(例如通过JNI)使用的内存占用虚拟内存,但不占用Java堆
  3. Java从操作系统请求的内存,但尚未被Java使用,绝对是虚拟内存,但可以从Java角度报告为“免费”。

答案 1 :(得分:1)

显然,收集堆转储的工具会执行GC以减小转储的大小。由于可以生成GC的东西不应该产生OOM,因此更倾向于发现内存泄漏而不是解决内存使用问题。

答案 2 :(得分:0)

VM请求虚拟内存来存储各种数据。 VM然后分配一些内存来存储变量(即堆),本机代码(不是堆),保留一些尚未使用的内存。因此,虚拟内存严格大于堆。在堆和虚拟内存之间没有任何明确的关联,因为你可以编写一个简单的无限递归(堆将几乎与虚拟内存一样大)或在hello world程序中加载一个大的dll(堆远小于虚拟内存)。