使用 Java 代理获取给定 Java 类的实例数?

问题描述

是否可以使用 Java 代理来获取任何 Java 类的实例数? 例如,如果我们有

class Apple {
...
}

Java 代理将返回 JVM 中有多少个 Apple 实例。 如果使用 Java 代理无法实现,是否可以通过另一种跨平台方式实现——并且不启用调试模式(因此不包括 jvmtijdi)?

解决方法

为了计算实例数,您需要遍历整个堆。 Java 代理没有这样的功能。基本上,他们只有Instrumentation API

使用 JVM TI 可以轻松完成任务。有 IterateOverInstancesOfClass 函数几乎可以满足您的需求。 JVM TI 不是跨平台的,但您可以为主要支持的平台创建一个带有动态库的 JAR,并在运行时加载合适的库。例如,这就是 JNA 的工作方式。

最接近的纯 Java 替代方法是获取类直方图的 HotSpot 诊断命令:

String histogram = (String) ManagementFactory.getPlatformMBeanServer().invoke(
        new ObjectName("com.sun.management:type=DiagnosticCommand"),"gcClassHistogram",new Object[]{null},new String[]{"[Ljava.lang.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
                       ...

虽然这不是标准 API。