繁体   English   中英

堆转储!=虚拟内存?

[英]Heap dump != virtual memory?

并不真正了解Java,尤其是Java调试,但是在Jenkins中使用Monitoring进行堆转储,然后在Eclipse中使用MAT对其进行解码,显示总内存使用了169.4 MB,而在Jenkins中,监视内存似乎经常使用很多和GC频繁运行。 -XmX是4G。

为何只有MAT获得169.4 MB? 可能是因为在进行转储之前,詹金斯执行了GC吗? 如果是这样,是否可以避免看到完整的内存转储?

了解记忆

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

Java堆转储仅包含与Java相关的内存,即Java对象所在的位置。 Java堆转储使用诸如MAT(如您所述)之类的工具Java Heap Analysis Tool进行分析。

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

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

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

在您的情况下, Monitoring很像一个通用工具,因为它处理的是进程列表和CPU时间,似乎没有什么是Java特定的。 另一方面,从其描述来看, MAT显然是一种Java工具。

记忆差异

那么Java堆大小与虚拟内存大小有多少不同?

许多:

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

显然,收集堆转储的工具会执行GC以减小转储的大小。 由于可以被GC化的东西不应该产生OOM,因此它的目的是发现内存泄漏而不是对内存使用进行故障排除。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM