有没有办法知道哪些对象在Heap的“旧”区域

时间:2012-06-12 11:42:51

标签: java garbage-collection jvm heap

我有很长的GC周期。 从检查中我看到堆中的旧()旧区域有太多物体。 有没有什么可以知道哪些对象在堆的哪个区域,或者关于这些对象的任何静态 我正在使用Sun / Oracle HotSpot JVM(Java 6)。

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

4 个答案:

答案 0 :(得分:7)

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

但另一方面,我不知道这样的实用程序会有多大帮助。

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

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

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

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


  

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

这开始变得更有意义了。听起来你需要找出哪些对象是长寿的......而不是具体到哪个空间。你可以通过使用jhat来比较一堆堆快照来做到这一点。 (可能有更好的方法......)

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

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

最后,目前还不清楚“优化对象创建”的含义。你的意思是降低对象的创建率吗?或者您是否正在考虑管理长期(缓存?)对象的保留?

答案 1 :(得分:1)

工具大象轨迹可以描绘对象的创建和死亡,elephantTrack。通过这种方式,您可以找出比预期更长的存活时间,并且通过方法历史记录,可以获得精确的对象。

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

答案 2 :(得分:0)

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

我已经习惯了Netbeans Profiler。它无法真正满足您的要求,但它有一个工具可以让您了解出了什么问题。

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

答案 3 :(得分:0)

我认为没有任何实用工具可以告诉你不同代的对象的数量。

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

    我认为这对你有帮助。