【问题标题】:Memory leaks of Garbage Collector objects垃圾收集器对象的内存泄漏
【发布时间】:2012-01-03 19:19:19
【问题描述】:

我的应用程序中存在严重的内存泄漏。我运行了 jmap,它说目前有以下不应该存在的对象(并且是泄漏的主要来源):

java.lang.management.MemoryUsage - 3938500 instances, 189048000 bytes
[Ljava.lang.management.MemoryUsage - 787700 instances, 31508000 bytes
com.sun.management.GCInfo - 293850 instances, 22055600 bytes
sun.management.GCInfoCompositeData - 393850 instances, 12603200 bytes

我不直接使用这些对象。但是它们被垃圾收集器使用。 我用:

Java version: 1.7.0-b147
VM version: Java Hotspot(TM) 64-bit Server VM (build 21.0-b17, mixed mode)
The application is run in Jetty version 7.3.1

我目前使用并发低暂停垃圾收集器。但是,即使在运行吞吐量收集器时,我也遇到了同样的问题。

你知道为什么这些对象会留在内存中吗?你会建议做什么?

更新:Java 1.7 更新 1(1.7.0_01-b08,Java Hotspot(TM) 64 位服务器 VM(内部版本 21.1-b02,混合模式))仍会发生内存泄漏

更新 2:内存泄漏是由 JConsole 引起的。在 JConosole 启动之前,没有上面提到的类的实例。一旦我使用 JConsole 连接到应用程序,对象就会开始出现在内存中,并且它们会永远保留在那里。在我关闭 JConsole 后,对象仍在内存中,并且它们的数量还在增长,直到应用程序关闭。

【问题讨论】:

  • 热点编译器循环优化存在bug。这可能是出现问题的原因。升级到 1.7.1
  • GC 不使用这些类。然而,监控 GC 的组件使用这些类来获取有关 GC 的信息。
  • 我猜这些是开启 GC 跟踪的产物。
  • 您是否打开了某种分析或跟踪来追踪内存泄漏?我曾经遇到过使用 hprof 代理引起的 classlaoder 泄漏。花了很长时间才发现这一点,它掩盖了最初只会偶尔出现的问题。
  • 我使用的是 JConsole,它除了其他功能外还监控内存。这可能是这些对象在内存中的原因,但即使现在当 JConsole 关闭时,内存中上述对象的数量仍在增长。

标签: java memory-leaks garbage-collection


【解决方案1】:

我并没有真正使用过 jmap,但我已经在我们的应用程序中处理了内存泄漏问题。

您的应用程序是否内存不足?我建议在应用程序关闭之前转储,将以下内容添加到您的 vm args

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp

当您的应用程序 oom 时,它会在 tmp 下创建一个 hprof 文件,您可以使用它来调试问题。

如果没有 OOM,请尝试分配较低的内存,以便您可以强制 OOM。

我使用eclipse MAT 来分析这些文件。它非常好,因为它会立即告诉您泄漏的嫌疑人。

【讨论】:

【解决方案2】:

我认为您需要提供有关该应用的用途和用途的更多详细信息。您只是使用 jConsole 来跟踪这个问题吗?

我使用 Visual VM 来跟踪这些类型的问题。请参阅此link,了解如何将其用于内存泄漏,以及此用于 Visual VM main page

【讨论】:

    【解决方案3】:

    我也有同样的问题。 2个月前我做了调查,问题出在JAVA 7_0虚拟机上。在我的场景中,java.lang.management.MemoryUsage 对象挂起并且每天增长数百 MB。您看到的所有其他挂起的对象都由 java.lang.management.MemoryUsage 对象引用。问题是,这个 MemoryUsage 对象只在 java 7_0 和更高版本中挂起,因为这个 MemoryUsage 类已添加到 JAVA 7 中,而以前的 java.util.最重要的是,这个 MemoryUsage 类只有在我使用 JConsole 连接到服务器后才会挂在内存中。 JConsole第一次连接后,会创建一些MemoryUsage跟踪机制,开始创建MemoryUsage对象。然后使用这些对象在 JConsole 中绘制漂亮的图形。这一切都好。但是,问题是,JAVA 7 是错误的,并且从不释放内存。 MemoryUsage 对象永远挂在堆上。关闭 JConsole 没关系,之后它会继续增长。第一次使用 JConsole 连接到 JAVA 7_0 进程时,您创建了问题并且没有解决方案。只是不要使用Jconsole,或者任何其他内存监控工具,或者不要使用Java 7。在我的场景中,我注定要失败,因为我必须一直使用Jconsole,而JAVA 6对我来说是没有选择的,因为还有另一个错误,由于锁定对象而导致内存泄漏。我向 ORACLE 报告了这个错误,但我不知道他们是否得到了它,知道它并正在解决它。我只是在等待更新版本的 java,所以我可以测试它并停止每隔几天重新启动我的服务器。

    【讨论】:

    【解决方案4】:

    几年前我向 Oracle 报告了一个问题,在 JDK 7 中,内存泄漏会在您连接 JConsole 的那一刻开始。泄漏将永远存在;即使您断开 JConsole。

    泄露了什么?与垃圾收集器运行原因相关的对象。实际上主要是字符串(例如“分配失败”)。我只发现了这个问题,因为我使用了 YourKit,并且在 YourKit 中,您可以分析标记为可回收垃圾的对象。基本上这些对象没有被我的应用程序中的任何东西引用,但它们也没有被垃圾收集器收集。

    大多数堆转储工具会立即从分析中删除可收集垃圾的对象。因此,YourKit 在确定错误确实存在于 JVM 中至关重要。

    找不到我的票,但我找到了其他票: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7143760 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7128632

    【讨论】:

      猜你喜欢
      • 2018-05-10
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-02
      • 2012-05-21
      • 1970-01-01
      相关资源
      最近更新 更多