11

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

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

4

4 回答 4

7

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

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

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

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

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

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


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

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

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

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

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

于 2012-06-12T11:56:13.457 回答
1

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

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

于 2014-08-26T22:59:43.263 回答
0

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

我习惯于 Netbeans Profiler。它不能真正做到你所要求的,但它有一个工具可以让你知道出了什么问题。

使用 Profiler 运行应用程序,选择Memory,然后在Live Results您的列Generations中。它没有告诉您每个对象的生成,但它为您提供了Surviving Generations. 因此,如果该数字大于 1,则它可能在终身(可能在幸存者空间)中,如果该数字一直在增长,则您有内存泄漏

于 2012-06-12T12:07:50.580 回答
0

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

  1. 一种方法是您可以使用jconsolejdk附带的。在 jconsole 的帮助下,您可以连接到您的应用程序并监视所有代,在这里您可能会得到一些我不确定的数字。
  2. 另一种方法是您可以使用 Eclipse工具进行转储jmap,然后对其进行分析。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

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

于 2012-06-12T12:20:39.250 回答