【问题标题】:is there a way to know which objects are in "old" area of Heap有没有办法知道哪些对象在堆的“旧”区域
【发布时间】:2023-03-10 11:44:01
【问题描述】:

我有很长的 GC 周期。 从检查中我看到堆的永久(旧)区域中有太多对象。 是否有任何实用程序可以知道哪些对象位于堆的哪个区域,或者关于这些对象的任何静态信息。
我正在使用 Sun/Oracle HotSpot JVM (Java 6)。

编辑:关于我的问题的更多细节:
我有一个大堆(32GB),看起来即使堆旧区域只有 30% 已满,手动运行 GC 也会暂停 15 秒。我想知道哪些对象是留在旧区的“幸存者”,以便知道要优化哪个对象创建。

【问题讨论】:

标签: java garbage-collection jvm heap-memory


【解决方案1】:

我不知道有任何工具/实用程序适用于当前一代 JVM。

但另一方面,我看不出这样的实用程序会有什么帮助。

通常会出现较长的 GC 时间,因为您的堆太满了。随着堆接近 100% 满,在 GC 中花费的时间往往呈指数增长。在最坏的情况下,堆完全填满,您的应用程序会收到OutOfMemoryError。有两种可能的解决方案:

  • 如果根本原因是堆太小(对于您的应用程序试图解决的问题的大小),那么要么增加堆大小,要么寻找减少应用程序工作集的方法;即在计算过程中需要“存活”的对象的数量/大小。

  • 如果根本原因是内存泄漏,则查找并修复它。

在这两种情况下,使用内存分析器都可以帮助您分析问题。但是你不需要知道老年代中有哪些对象。它与问题的根本原因或问题的解决方案无关。


我想知道哪些对象是留在旧区的“幸存者”,以便知道要优化哪些对象创建。

这开始变得更有意义了。听起来您需要找出哪些对象是长期存在的……而不是具体地找出它们所在的空间。您可以通过使用jhat 比较一系列堆快照来做到这一点。 (可能有更好的方法……)

但是,我仍然认为这种方法没有帮助。问题是完整的 GC 需要遍历所有可到达的(硬、软、弱、幻)对象。而且,如果您有一个 32Gb 堆已满 30%,那么您仍然有很多对象需要标记/清除/重定位。我认为解决方案很可能是使用并发收集器并对其进行调整,使其能够跟上应用程序的对象分配率。

听起来您可能会直接从您的代码中调用System.gc()不要那样做!调用System.gc() 将(通常)导致JVM 进行完整 垃圾回收。这几乎是保证让你暂停一下。让 JVM 决定何时运行收集器要好得多。

最后,不清楚您所说的“优化对象创建”是什么意思。你的意思是降低对象创建率?或者您是否正在考虑其他方法来管理长期(缓存?)对象的保留?

【讨论】:

  • 在尝试查找内存泄漏时知道哪些对象位于旧区域中会不会有帮助?因为即使在完整的 gc 之后,长寿(引用的对象)也应该在那里并且不被清理,对吧?
  • 嗯...我不这么认为。如果有足够的对象流失,那么长期存在的对象将可能最终被永久使用。但这是 GC 特有的行为。无论哪种方式,该信息都不是确定对象是否泄漏的必要或充分条件。而且(AFAIK)无论如何都没有信息。所以你的想法没有实际意义......除非你打算开始在 OpenJDK 代码库上进行黑客攻击来实现它......
【解决方案2】:

工具大象轨迹可以分析对象的创建和死亡,elephantTrack。有了这个,你也许能够弄清楚什么样的对象比预期的存活时间更长,并且通过方法历史,有可能得到准确的对象。

但是大堆意味着很长的配置文件时间和非常大的配置文件。

【讨论】:

  • 但是......根据网站,它不适用于 Java 1.7 和(大概)更高版本。
【解决方案3】:

我从未见过允许“探索”给定世代中的对象的工具。

我习惯于 Netbeans Profiler。它不能真正满足您的要求,但它有一个工具可以让您了解问题所在。

使用 Profiler 运行应用程序,选择 Memory,然后在 Live Results 中有一列 Generations它不会告诉你每个对象的世代,但它会告诉你Surviving Generations 的数量。因此,如果该数字大于 1,则它可能在终身(可能在幸存者空间)中,如果数字一直在增长,那么您就有内存泄漏

【讨论】:

    【解决方案4】:

    我认为没有任何实用程序可以告诉您不同代的对象数量。

    1. 一种方法是您可以使用 jdk 附带的jconsole。在 jconsole 的帮助下,您可以连接到您的应用程序并监控所有代,在这里您可能会得到一些我不确定的数据。
    2. 另一种方法是您可以使用jmap 进行转储,然后使用eclipse MAT 工具对其进行分析。
    3. 或者您可以使用以下JVM 参数运行您的应用程序,并在日志中获得有关 GC 的信息

    GC logging is enabled using JVM arguments; below are the arguments I use. (Note: the log file specified as file is reset each time the VM starts.

    -verbose:gc -Xloggc:file

    我认为这可能对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-08
      • 2013-09-10
      • 2010-11-10
      相关资源
      最近更新 更多