Java 内存泄漏,VisualVM 显示错误数据。

6

我有一个Java应用程序在运行,几个小时后就会占满内存。

我尝试使用VisualVM检测内存泄漏,但它显示错误的数据(不知道怎么会出现这种情况)。

在屏幕截图中,您可以看到任务管理器显示700Mb的内存使用情况,而VisualVM只显示225...

有人知道这里发生了什么吗?

谢谢!

enter image description here


2
如果发生内存泄漏,请将-XX:PermSize = 256m -XX:MaxPermSize = 256m设置为VM参数。 - lakshman
@Vach,这看起来不像是内存泄漏... - assylias
@lakshman,这并没有解决PermGenSize内存泄漏问题,它只是推迟了实际的问题。更好的建议是提出一个框架,如果不再需要/使用类,则可以卸载它们。然而,这需要智能类加载和进一步严格处理(特别是单例和枚举)。 - Roman Vottner
OFFTOP:有没有可能放大图像? - Tomasz Waszczyk
1
@Vach 我根本没有提到这些参数 - 我只是评论说它们不能解决问题,而只是会推迟解决。在我看来,发现内存泄漏的最佳方法是将lakshman给出的参数降至最低,并使用分析器生成堆转储文件,然后开始更详细地分析。为什么要减少内存?因为这将促使GC更快地运行,您的问题可能会更早地出现。此外,堆转储文件也不会占用太多磁盘空间。 - Roman Vottner
显示剩余5条评论
3个回答

4
要注意的是,操作系统只知道Java在一段时间内保留的总内存量(而且据我所知,Java不会轻易地返回该内存量)。然而,在某个时刻,Java可能并没有使用所有这些内存,因此您可能会看到这两个数字之间的差异。
例如,如果您像这样启动程序:
java -Xmx512m -Xms256m ...

当JVM启动时,它会立即占用256 MB的内存(操作系统会告诉你这个数字大概是多少)。然而,如果你打开内存监视工具(如visualvm、jconsole等),它可能会显示你使用的内存比这个要少(只是因为你还没有需要使用到整个堆内存的大小)。


“好的,“它可以显示我使用的少于那个”但是如果我使用-Xmx512运行给定的Java应用程序,这是否意味着512是为该应用程序定义的最大内存,并且任务管理器理论上不应显示超过512的更多分配?还是我没有理解什么?” - vach
1
那将是最大堆大小,但还有其他区域占用更多的操作系统空间(除了JVM需要自己将其自己的代码和变量放入内存的空间)。将其视为方向(但设置JVM限制非常有用)。 - Jorge_B

3
Java不会把获取的内存返回。分配内存需要很大的努力,因此Java通常不会返回系统授予的任何内存。因此,如果您的程序曾经使用过760MB RAM,则它将保留该内存。

然后还有另外两个重要的因素。堆大小仅为程序使用或可以使用的内存量。但是在程序和操作系统之间存在Java虚拟机,可能也会占用相当多的内存。任务管理器显示您的程序加上VM使用的内存量。

另一个因素是内存碎片。某些数据结构(例如数组)必须位于内存的连续块中。array [i + 1] 必须位于 array [i] 后面的内存插槽中。这意味着,如果您已经分配了10 MB内存,并且使用了中间2 MB内存,而您想创建一个6 MB的数组,则Java虚拟机必须分配新内存,以便将数组放入一个块中。 这会增加任务管理器中的内存使用量,但不会增加堆大小,因为堆大小仅显示实际使用的内存。


3
事实上,GC通过在清理和释放未使用的对象时重新定位内存来处理您所描述的“碎片整理”问题。 - Roman Vottner
1
好的,理解了。嗯,这可能只会在垃圾回收运行时才实现,而分配可能不会同时进行。特别是因为没有关于垃圾回收运行时间的硬性标准。 - Dakkaron

2
在Java中,内存空间由三个指标定义:已使用、可用和最大可用(参见JMX值)。您看到的大小是可用大小而不是最大可用大小,后者可能已经分配。 另外,您还应该显示非堆内存(通常小于堆,但您应该以不同的设置进行设置)。 为了更精确,您应该发布您的JVM启动设置。
PS:从您的内存配置文件中看不到任何泄漏:我可以看到JVM缩小堆大小,因为根本没有使用。

如果你看VisualVM,你看不到任何泄漏,那任务管理器呢? - vach
在任务管理器中,您可以查看每个进程分配的内存。 JVM根据Java启发式和JVM设置向操作系统请求其活动所需的内存,即使内存中没有任何对象。向操作系统请求新的内存是昂贵的,如果可能的话,JVM将避免这样做。发布您的JVM设置,以获得您问题的最终解决方案。 - SpyGlassTools.com

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接