Search code examples
javajvmjavaagentsjvmtijdi

Get number of instances of a given Java class using a Java agent?


Is it possible to use a Java agent to get the number of instances of any Java class? For example if we have

class Apple {
...
}

The Java agent will return how many Apple instances are there in the JVM. If it's not possible with a Java agent, is it possible to do it in another cross-platform manner - and without debug mode enabled (so JVMTI and JDI excluded)?


Solution

  • In order to count instances, you'll need to walk through the entire heap. Java Agents don't have such functionality. Basically, all they have is Instrumentation API.

    The task is simple to do with JVM TI. There is IterateOverInstancesOfClass function which does almost what you want. JVM TI is not cross-platform, but you may create a JAR with dynamic libraries for the main supported platforms, and load the suitable one in runtime. That's how JNA works, for example.

    The closest pure Java alternative is HotSpot diagnostic command to get a class histogram:

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

    Among other things, it returns the number of instances of each class:

     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
                           ...
    

    This is not a standard API though.