虽然我对Java和特别是Java调试不是很了解,但使用Monitoring在Jenkins中获取堆转储,并在Eclipse中使用MAT进行解码后,显示总内存使用量为169.4 MB,而在Jenkins监视器中,内存似乎一直被大量使用,并且频繁运行GC。-XmX为4G。
为什么我只能用MAT得到169.4 MB?这可能是因为在进行转储之前,Jenkins执行了GC吗?如果是这样,我能否避免它以查看完整的内存转储?
虽然我对Java和特别是Java调试不是很了解,但使用Monitoring在Jenkins中获取堆转储,并在Eclipse中使用MAT进行解码后,显示总内存使用量为169.4 MB,而在Jenkins监视器中,内存似乎一直被大量使用,并且频繁运行GC。-XmX为4G。
为什么我只能用MAT得到169.4 MB?这可能是因为在进行转储之前,Jenkins执行了GC吗?如果是这样,我能否避免它以查看完整的内存转储?
是的,Java堆转储和虚拟内存转储(在Windows上称为“崩溃转储”或“内存转储”)是不同的东西。
Java堆转储仅包含与Java相关的内存,即Java对象所在的位置。可以使用MAT(如您所提到的)或Java堆分析工具等工具来分析Java堆转储。
(用户模式)进程的Windows崩溃转储包含所有虚拟内存,其中虚拟内存是操作系统提供内存的术语。在Windows上,这是通过VirtualAlloc分配的所有内存。
操作系统虚拟内存将包括Java堆,因为Java只能从操作系统请求内存。
因此,在比较内存大小时,重要的是要了解工具是针对Java还是操作系统的。
在您的情况下,监控看起来很像一个通用工具,因为它处理进程列表和CPU时间,似乎没有Java特定的内容。另一方面,从其描述中可以清楚地看出,MAT是一个Java工具。
那么Java堆大小与虚拟内存大小相差多少呢?
很多:
monitoring
实际上是监视Jenkins JVM而不是操作系统。 - Zloj虚拟机请求虚拟内存来存储各种数据。然后,虚拟机分配一些内存来存储变量(即堆),本地代码(非堆),保留一些尚未使用的内存。因此,虚拟内存严格大于堆。由于您可以编写简单的无限递归(堆将几乎与虚拟内存一样大)或在 hello world 程序中加载大型 dll(堆比虚拟内存小得多),因此堆和虚拟内存之间没有明显的相关性。