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

问题描述

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

class Apple {
...
}

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

解决方法

为了计算实例数,您需要遍历整个堆。 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。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...