【问题标题】:Java GC strange behaviour or memory leak?Java GC 奇怪的行为或内存泄漏?
【发布时间】:2013-04-28 10:30:58
【问题描述】:

我正在开发一个 Swing 应用程序,最近,我开始看到以下问题:

我必须在一个单独的窗口中显示一个非常大的工作报告。我关闭此窗口,然后重新打开同一个作业报告,并收到 OutOfMemory Java 堆空间错误。

JVM 以 -Xmx512m 启动,当我打开作业报告时创建的所有对象在堆上占用大约 300MB。假设没有内存泄漏,我希望第二次打开相同的作业报告时 JVM 不会抛出 OOM。但是,在关闭第一个窗口后查看 GC 日志,我没有看到任何 GC 活动。

奇怪的是,在我关闭第一个窗口后,如果我使用 jmap 进行堆转储(没有“live”选项),仍然可以在堆转储中看到对象。

如果我使用 dump:live 选项运行 jmap,会发生以下情况:

  • 进行第一次堆转储后,我仍然可以看到堆上的对象。
  • 当我进行第二次堆转储时,它不再包含那些对象,我可以再次重新打开相同的作业报告,没有任何问题。 那么,如果是内存泄漏,那么这些对象就不会被收集,对吗?

我在 Java 6(1.6.0_25 和 1.6.0_45,在 Windows 上)上对此进行了测试,它一直在重现。

运行 jmap -heap 打印:

"using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 536870912 (512.0MB)
   NewSize          = 1048576 (1.0MB)
   MaxNewSize       = 4294901760 (4095.9375MB)
   OldSize          = 4194304 (4.0MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 12582912 (12.0MB)
   MaxPermSize      = 134217728 (128.0MB)

"

JVM 使用以下选项启动:

"   -Xms128m
    -Xmx512m
    -XX:MaxPermSize=128M
    -verbose:gc
    -XX:+PrintGCTimeStamps
    -XX:+PrintGCDetails
    -Xloggc:c:\my_gc.log
    -XX:+HeapDumpOnOutOfMemoryError"

所以,我的问题是:为什么当我使用 live 选项进行堆转储时会收集所有对象(表明没有内存泄漏)但是,如果我不这样做,我将无法因为我收到 OOM 错误而重新打开另一个(或相同的)工作报告?

另外,我测试了另一个场景:

  • 打开第一个作业报告窗口,然后将其关闭。
  • 创建了一个菜单项,当按下该菜单项时,会在无限循环中创建 Long 实例,直到 JVM 抛出 OOM。 我检查了在抛出 OOM 时生成的堆转储,堆中 99% 被 Long 实例填充,并且我的作业报告对象都没有在堆上。

提前致谢。

【问题讨论】:

    标签: java memory-leaks garbage-collection out-of-memory heap-memory


    【解决方案1】:

    所以,我的问题是:为什么当我拿 使用 live 选项进行堆转储

    jmap live 选项强制收集。已经讨论过here

    您的观察证实了这一点。

    可以做的一个练习是重新打开窗口发布一些 GC 活动以查看内存是否已被回收。

    【讨论】:

      猜你喜欢
      • 2013-05-03
      • 1970-01-01
      • 2012-07-06
      • 2015-05-09
      • 2021-03-28
      • 2020-12-19
      • 2011-04-01
      • 2012-03-07
      相关资源
      最近更新 更多