【问题标题】:java memory leak, visualvm showing wrong datajava内存泄漏,visualvm显示错误数据
【发布时间】:2014-02-18 01:00:16
【问题描述】:

我有一个 Java 应用程序正在运行,几个小时后它会填满内存。 我尝试使用 visualvm 检测内存泄漏,但它显示了错误的数据(不知道这是怎么发生的)。

在屏幕截图中,您可以看到任务管理器显示内存使用量为 700Mb,visualvm 显示为 225...

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

问候

【问题讨论】:

  • 如果发生内存泄漏设置 -XX:PermSize=256m -XX:MaxPermSize=256m 作为 VM 参数
  • @Vach 这看起来不像是内存泄漏...
  • @lakshman 这根本不能解决 PermGenSize 内存泄漏,它只是延迟了实际问题。更好的建议是提出一个框架,如果不再需要/使用它们,它实际上能够卸载类。然而,这需要智能类加载并进一步进行相当严格的处理(尤其是单例和枚举)
  • OFFTOP: 可以放大图片吗?
  • @Vach 我根本没有提到这些参数 - 我只是评论说它们不会解决问题,而不仅仅是延迟它。在我看来,发现内存泄漏的最佳方法是在给定 lakshman 提供的参数的情况下将给定内存减少到最低限度,然后使用分析器生成堆转储,然后您可以开始更详细地分析。为什么要减少内存?因为这将更快地强制 GC,并且您的问题可能会更早发生。此外,堆转储也不会占用太多磁盘空间。

标签: java memory-leaks profiling visualvm


【解决方案1】:

请注意,您的操作系统只知道 java 在一段时间内保留的内存总量(并且 java 不会轻易返回该内存量 AFAIK)。但是,java 可能不会在给定时刻使用所有内存,因此您可以看到这两个数字之间的差异。

例如,如果您像这样启动程序

java -Xmx512m -Xms256m ...

然后,您的 JVM 将在启动后立即占用 256 MB(操作系统或多或少会告诉您)。但是,如果您打开内存查看工具(无论是 visualvm、jconsole 等),它可能会显示您使用的内存少于此数量(只是您不需要使用整个保留堆)。

【讨论】:

  • 好的“它可以显示我使用的内存少于那个”但是如果我使用 -Xmx512 运行给定的 java 应用程序,这是否意味着 512 是为该应用程序和任务管理器定义的最大内存理论上不应该显示更多的配置,512?还是我没听懂?
  • 这将是最大堆大小,但还有其他区域占用更多操作系统空间(JVM 需要自己将自己的代码和变量放入内存中的空间)。将其作为一个方向(但对设置 JVM 限制非常有用)
【解决方案2】:

Java 得到的东西不会返回。分配内存需要付出很多努力,因此 Java 通常不会返回系统曾经授予它的任何内存。因此,如果您的程序曾经使用过 760 MB RAM,那么这就是它所坚持的。

还有另外两个因素起着重要作用。堆大小只是您的程序使用或可以使用的内存量。但是在您的程序和操作系统之间是 Java-VM,它也可能占用大量内存。任务管理器会显示您的程序使用的内存量以及虚拟机。

另一个因素是内存碎片。某些数据结构(例如数组)必须位于内存的连续块中。 array[i+1] 必须在 array[i] 之后的内存槽中。这现在意味着如果你有例如分配了 10 MB 内存,中间的 2 MB 内存被使用,你想创建一个 6 MB 的数组,Java-VM 必须分配新的内存,所以它可以将数组放在一块。 这会增加任务管理器中的内存使用量,但不会增加堆大小,因为堆大小只显示实际使用的内存。

【讨论】:

  • 实际上,GC 通过在清理和释放未使用的对象时重新定位内存来处理您所描述的“碎片整理”问题。
  • 好吧,有道理。好吧,它可能只会在 GC 运行时这样做,这可能与分配不同时。尤其是因为没有关于 GC 何时运行的硬性标准。
【解决方案3】:

Java 中的内存空间由 3 个指标定义:已用、可用、最大可用(请参阅 JMX 值)。您看到的大小是可用大小而不是最大可用大小,可能已经分配。 同样,您还应该显示非堆内存(通常小于堆,但您应该以不同的方式设置它) 更准确地说,您应该发布您的 JVM 启动设置。

PS:查看您的内存配置文件我看不到任何泄漏:我可以看到 JVM 正在缩小堆大小,因为它根本没有被使用

【讨论】:

  • 好吧,如果您查看 visalvm,您没有发现任何泄漏,那么任务管理器呢?
  • 在任务管理器中你可以看到进程分配的内存。即使内存中没有对象,JVM 也会根据 java eu​​ristics 和 jvm 设置向操作系统内存请求其活动。向操作系统请求新内存是昂贵的,如果可能的话,JVM 会避免它。发布您的 JVM 设置以最终解决您的问题。
猜你喜欢
  • 2013-03-04
  • 1970-01-01
  • 2015-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-27
  • 2017-01-29
  • 1970-01-01
相关资源
最近更新 更多