不是真正了解Java,特别是关于Java的调试,但是使用Monitoring在Jenkins中进行堆转储,然后使用MAT在Eclipse中对其进行解码,显示总内存使用了169.4 MB,而在Jenkins监控内存似乎经常被大量使用并且GC经常运行。 -XmX是4G。
为什么我只用MAT获得169.4 MB?可能是因为在进行转储之前Jenkins执行GC吗?如果是这样,我可以避免它看到完整的内存转储吗?
答案 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 :(得分:1)
显然,收集堆转储的工具会执行GC以减小转储的大小。由于可以生成GC的东西不应该产生OOM,因此更倾向于发现内存泄漏而不是解决内存使用问题。
答案 2 :(得分:0)
VM请求虚拟内存来存储各种数据。 VM然后分配一些内存来存储变量(即堆),本机代码(不是堆),保留一些尚未使用的内存。因此,虚拟内存严格大于堆。在堆和虚拟内存之间没有任何明确的关联,因为你可以编写一个简单的无限递归(堆将几乎与虚拟内存一样大)或在hello world程序中加载一个大的dll(堆远小于虚拟内存)。