是否有一种简单的方法可以在Java中获取特定类的所有对象实例

时间:2009-12-22 15:33:13

标签: java jvm profiling

目前我正在使用Java代理来组装内存统计信息。在instrumentation API的帮助下,我可以掌握这些类(并操纵它们)。使用普通Java,我可以估计每个对象使用的资源。到目前为止,非常好。

我现在面临的问题是“如何掌握特定类的每个Object实例”。我可以进行字节代码操作以获取对象实例,但我希望有另一个我不知道的API,帮助我实现我的目标,没有这么大的侵入性步骤。最后,应将性能影响保持在最低限度。有什么想法吗?

6 个答案:

答案 0 :(得分:21)

Eclipse中的调试器可以show you all the instances of a class,所以我查看了Eclipse的源代码。 Eclipse使用Java Debug Wire Protocol,它允许您(从Java 6开始)查找所请求类的所有实例。如果您想沿着这条路走,请抓取Eclipse源代码的副本,并查看instances的{​​{1}}方法。

更简单的方法是使用Java Debug Interface。请注意ReferenceType.instances方法。

我还没有弄清楚如何使用JDI连接到正在运行的进程以及如何获取org.eclipse.jdi.internal.ReferenceTypeImpl的实例。 JDK包含多个examples,所以我确信它是可行的。

答案 1 :(得分:4)

当我读到这篇文章时,我认为必须有一些方法来获取这种信息,因为存在java分析器。也许这会有所帮助:http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html。它描述了JVM和探查器代理之间的接口。但如果你真的想用Java写这个,你可能会运气不好。

具体来说,看看这个功能:

jint (*EnableEvent)(jint event_type, void *arg);

    Called by the profiler agent to enable notification of a particular type of event. Apart from event_type, the profiler may also pass an argument that provides additional information specific to the given event type.

    All events are disabled when the VM starts up. Once enabled, an event stays enabled until it is explicitly disabled.

    This function returns JVMPI_NOT_AVAILABLE if event_type is JVMPI_EVENT_HEAP_DUMP, JVMPI_EVENT_MONITOR_DUMP or JVMPI_EVENT_OBJECT_DUMP. The profiler agent must use the RequestEvent function to request these events.

    Arguments:

        event_type  - type of event, JVMPI_EVENT_CLASS_LOAD etc.
        arg     - event specific argument.

    Returns:

        JVMPI_SUCCESS   enable succeeded.
        JVMPI_FAIL  enable failed.
        JVMPI_NOT_AVAILABLE     support for enabling the given event_type is not available. 

答案 2 :(得分:1)

http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html#IterateOverInstancesOfClass

您可以编写一些获取JVMTI指针的本机代码,然后将其用于 迭代给定类的所有实例,如上面的链接所示。 您可以从Java程序中调用此本机代码。 正如Eli指出的那样,从Java 6开始,这个称为Java调试接口的高级包装器允许您从Java本身进行此类调用,而不必使用本机代码。

希望这会有所帮助

拉​​姆

答案 3 :(得分:1)

我想知道您尝试做什么可能是使用BTrace完成的?

答案 4 :(得分:0)

从以前的帖子中我所说的,没有办法获得Java中所有类的实例列表。反射API做了一些巧妙的事情,但不是这个特定的东西。

你可以做的最好的事情是保持指向所有对象的指针,但这似乎是淫秽的,并不适用于其他人的程序。不太理想啊?

答案 5 :(得分:0)

如其他答案所述,您可以通过使用JDI协议来做到这一点。这非常简单:您需要使用

在调试模式下运行JVM。

-agentlib:jdwp = transport = dt_socket,server = y,suspend = n,address = 56855

之后,您可以连接到远程(或本地JVM)并列出指定类的所有实例。另外,您不能将远程对象直接转换为真实对象,但是可以访问远程对象的所有字段,甚至可以使用cal方法。

此处介绍了如何连接到远程JVM并获取VirtualMachine

    private static VirtualMachine attach(String hostname, String port) throws IOException, IllegalConnectorArgumentsException {
        //getSocketAttaching connector to connect to other JVM using Socket
        AttachingConnector connector = Bootstrap.virtualMachineManager().attachingConnectors()
                .stream().filter(p -> p.transport().name().contains("socket"))
                .findFirst().get();

        //set the arguments for the connector
        Map<String, Argument> arg = connector.defaultArguments();
        arg.get("hostname").setValue(hostname);
        arg.get("port").setValue(port);

        //connect to remote process by socket
        return connector.attach(arg);
    }

获取VirtualMachine之后,您可以使用classesByName方法和实例获取类的实例。它返回ReferenceType的列表:

         VirtualMachine vm = attach("localhost", "56856");

        //get all classes of java.lang.String. There would be only one element.
        List<ReferenceType> classes = vm.classesByName("java.lang.String");

        //get all instances of a classes (set maximum count of instannces to get).
        List<ObjectReference> o = classes.get(0).instances(100000);

        //objectReference holds referenct to remote object. 
        for (ObjectReference objectReference : o) {
            try {
                //show text representation of remote object
                System.out.println(objectReference.toString());
            } catch (com.sun.jdi.ObjectCollectedException e) {
                //the specified object has been garbage collected
                //to avoid this use vm.suspend() vm.resume()
                System.out.println(e);
            }
        }

这里是程序的working example,它运行并连接到自身并列出java.lang.String的所有实例。要运行示例,您需要在类路径中使用jdk中的tool.jar。