首页 > 解决方案 > JVM 以编程方式获取堆中最大的对象

问题描述

如何以编程方式(从 java 应用程序/代理中)获得堆中最大对象的“实时”摘要(包括它们的实例数和大小)?

与 Profilers 所做的类似。

例如,下面是 JProfiler 的截图:

活体

通常我曾经在我真正需要的情况下使用堆转储,但现在我想弄清楚探查器如何从正在运行的 JVM 中准确地检索到这种信息,而无需实际进行堆转储。

是否可以通过使用 Java API 获取此类信息?如果不可能,本机代码中的替代方案是什么?代码示例最适合我的需要,因为 java 世界的这个特定部分对我来说真的很新。

我有点相信,如果我有兴趣找到一些真正具体的类的信息,我可以使用仪器或其他东西,但据我所知,它使用采样,所以应该有另一种方式。

我目前正在使用在 linux 上运行 java 8 的 HotSpot VM,但是我会找到更“通用”的解决方案 - 更好。

标签: javajvmprofilingheap-memoryprofiler

解决方案


没有用于堆遍历的标准 Java API。但是,有一个特定于 HotSpot 的诊断命令可以通过 JMX 调用:

String histogram = (String) ManagementFactory.getPlatformMBeanServer().invoke(
        new ObjectName("com.sun.management:type=DiagnosticCommand"),
        "gcClassHistogram",
        new Object[]{null},
        new String[]{"[Ljava.lang.String;"});

这将收集类直方图并以单一格式返回结果String

 num     #instances         #bytes  class name
----------------------------------------------
   1:          3269         265080  [C
   2:          1052         119160  java.lang.Class
   3:           156          92456  [B
   4:          3247          77928  java.lang.String
   5:          1150          54104  [Ljava.lang.Object;
   6:           579          50952  java.lang.reflect.Method
   7:           292          21024  java.lang.reflect.Field
   8:           395          12640  java.util.HashMap$Node
                       ...

内容相当于jmap -histo命令的输出。

堆遍历的唯一标准API 是本机 JVM TIIterateThroughHeap函数,但它并不那么容易使用,而且它的工作速度比上面的诊断命令慢得多。


推荐阅读