【问题标题】:JVM Getting the largest objects in the heap programmaticallyJVM 以编程方式获取堆中最大的对象
【发布时间】:2021-07-12 21:11:17
【问题描述】:

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

类似于 Profiler 的工作。

例如,下面是 JProfiler 的截图:

通常我在真正需要的情况下使用堆转储,但现在我想弄清楚探查器如何在不实际进行堆转储的情况下从正在运行的 JVM 中检索此类信息。

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

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

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

【问题讨论】:

  • Java Flight Recorder 公开了一个流式 API。 docs.oracle.com/en/java/javase/16/jfapi/why-use-jfr-api.html
  • 使用Java的反射机制(Class类)及其方法获取方法名。正常获取实例计数并占用内存,使用总内存和相关 api 来获取所有对象的总内存。希望这会有所帮助。

标签: java jvm profiling heap-memory profiler


【解决方案1】:

没有用于堆遍历的标准 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 TI IterateThroughHeap 函数,但它不是那么好用,而且它的工作速度比上面的诊断命令慢很多。

【讨论】:

  • ... JVM TI 不能被 JVM 用来对付自己。
  • 非常感谢安德烈和斯蒂芬!我要补充一点,通过 JMX 调用这个 MBean 需要一个标志 -XX:+UnlockDiagnosticVMOptions。它是否对正在运行的进程有任何已知的性能影响,这意味着我可以默认为我们所有的应用程序指定它吗?除此之外,我很乐意接受答案。另外我在“深入兔子洞”并问了一个后续问题:stackoverflow.com/questions/67156225/…也许你可以看看。再次感谢!
  • @MarkBramnik 不,它不需要UnlockDiagnosticVMOptions。性能影响是堆遍历期间的 stop-the-world JVM 暂停(持续时间与堆使用量成正比)。
猜你喜欢
  • 2021-07-13
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 2010-09-30
  • 2011-01-16
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
相关资源
最近更新 更多