堆转储!=虚拟内存?

Heap dump != virtual memory?

并不真正了解 Java,尤其是 Java 中的调试,但使用 Monitoring and then decoding it in Eclipse with MAT 在 Jenkins 中进行堆转储显示使用的总内存为 169.4 MB,而在 Jenkins 监控中内存似乎经常被使用,GC 经常 运行。 -XmX为4G.

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

显然,收集堆转储的工具执行 GC 以减小转储的大小。由于可以进行 GC 处理的事物不应产生 OOM,因此这是为了查找内存泄漏而不是解决内存使用问题。

理解记忆

是的,Java 堆转储和虚拟内存转储(在 Windows 上称为 "crash dump" 或 "memory dump")是不同的东西。

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

等工具进行分析

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

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

因此,在比较内存大小时,了解该工具是 Java 特定的还是 OS 通用的很重要。

在你的例子中,Monitoring 看起来很像一个通用工具,因为它处理进程列表和 CPU 次,似乎没有什么 Java 具体。另一方面,MAT 从其描述来看显然是一个 Java 工具。

内存差异

那么 Java 堆大小与虚拟内存大小相差多少?

很多:

  1. 加载EXEs/DLLs帐户到虚拟内存,但未加载到Java堆
  2. 本机代码(例如通过 JNI)使用的内存计入虚拟内存,但不计入 Java 堆
  3. Java 从 OS 请求的内存,但 Java 尚未使用,肯定是虚拟内存,但可以报告为 "free" 来自 Java视角。

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