【问题标题】:How to automatically dump memory when old-gen of jvm exceeds some ratio?当老一代的jvm超过某个比例时如何自动转储内存?
【发布时间】:2014-04-23 14:51:21
【问题描述】:

我经常发现我繁忙的 java web 应用程序 full-gc。
并且我用jstat监控了这个过程,得到了如下结果:

Timestamp         S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC                 
  2265116.2   0.00  58.20  79.23  62.57  62.29 273122 5729.765   727  281.867 6011.632 unknown GCCause      No GC               
  2265117.3   0.00  58.20  86.92  62.57  62.29 273122 5729.765   727  281.867 6011.632 unknown GCCause      No GC               
  2265118.3   0.00  58.20  97.72  62.57  62.29 273122 5729.765   727  281.867 6011.632 unknown GCCause      No GC               
  2265119.3  48.51   0.00  13.06  62.84  62.29 273123 5729.791   727  281.867 6011.658 unknown GCCause      No GC               
  2265120.2  48.51   0.00  51.12  62.84  62.29 273123 5729.791   727  281.867 6011.658 unknown GCCause      No GC               
  2265121.3   0.00  42.79  35.43  65.35  62.29 273124 5729.830   727  281.867 6011.697 unknown GCCause      No GC               
  2265122.2   0.00  39.46  50.81  80.86  62.29 273126 5729.998   728  281.883 6011.881 CMS Initial Mark     No GC               
  2265123.3   4.43   4.82  75.57  97.05  62.29 273129 5730.176   729  281.883 6012.060 unknown GCCause      Allocation Failure  
  2265124.3   4.43   4.82  75.57  97.05  62.29 273129 5730.176   729  281.883 6012.060 unknown GCCause      Allocation Failure  
  2265125.3   0.00   7.89  26.93  45.03  62.27 273130 5730.259   729  283.690 6013.949 unknown GCCause      No GC               
  2265126.3   0.00   7.89  35.96  45.03  62.27 273130 5730.259   729  283.690 6013.949 unknown GCCause      No GC               
  2265127.3   0.00   7.89  44.85  45.03  62.27 273130 5730.259   729  283.690 6013.949 unknown GCCause      No GC               
  2265128.3   0.00   7.89  52.71  45.03  62.27 273130 5730.259   729  283.690 6013.949 unknown GCCause      No GC               
  2265129.3   0.00   7.89  61.61  45.03  62.27 273130 5730.259   729  283.690 6013.949 unknown GCCause      No GC

我可以看到,每隔 20 分钟左右,似乎就会在内存中创建一个非常巨大的对象。太大了,young-gen放不下,直接分配到old-gen中。
并且经常会导致整个应用程序命中 FGC retio(即 70%)并触发 FGC,大对象立即被 GC-ed。所以我无法通过堆转储确定它是什么。
这个问题使我的应用经常“地震”。
我的最大堆是 3g,年轻代是 521m。 perm-gen 始终是稳定的。
那么,谁能告诉我,我怎么知道这个巨大的物体到底是什么?
我可以将 jvm 配置为在 old-gen 超过某个指定比率时转储其内存吗?
或者任何其他有用的方法可以提供帮助?
非常感谢!

【问题讨论】:

  • 你指的是哪一行?旧代大小的唯一跳跃是在次要集合之后,这是完全正常的。我怀疑没有巨大的物体。
  • 您每隔几秒钟就会进行一次次要收集。我建议你增加 Eden 的大小,这样你就没有那么多年轻的集合了。
  • 我的意思是老一代的使用率在 2 或 3 秒内从 65.35% 跃升至 97.05%。由于我的老一代是 2.5GB 大,这通常意味着突然出现了一个非常巨大的物体。我想知道它是什么。
  • 您是否尝试过使用内存分析器?这将向您显示大型对象,但也会告诉您大部分垃圾来自哪里。 250 MB/秒是一个相当高的速率(但并非不合理)
  • 在跳转时有两个次要集合,因此可能是对象已被提升。在任何情况下,内存分析器都是您的最佳选择。

标签: java garbage-collection jvm dump


【解决方案1】:

如果大对象由 FullGC 进行 GC,您可以使用类直方图检查堆

使用-XX:+PrintClassHistogramBeforeFullGC-XX:+PrintClassHistogramAfterFullGC. 这至少会向您显示在堆中分配的所有不同类别的对象,按占用空间和实例数排序。

这是一种轻量级的方法,但您至少可以检查您对“一个大对象”的假设。之后,您可以使用分析器进行挖掘,例如JDK7u40 及更高版本或 jProfiler 的 Mission Control 都很好用。

【讨论】:

    【解决方案2】:

    有一个 JVM 标志可能会对您有所帮助:-XX:+HeapDumpBeforeFullGC。它将导致 JVM 在主要的 stop-the-world GC 之前将整个堆转储到文件中。该标志是可管理的。这意味着您可以通过 JMX 与 JConsole、Misson Control 甚至以编程方式使用 javax.management API 在运行时打开/关闭它:

    MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
            server,
            "com.sun.management:type=HotSpotDiagnostic",
            HotSpotDiagnosticMXBean.class);
    bean.setVMOption("HeapDumpBeforeFullGC", "true");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-01
      相关资源
      最近更新 更多