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

uajslkp6  于 2022-11-07  发布在  Java
关注(0)|答案(6)|浏览(193)

目前,我正在开发一个Java代理来组装内存统计信息。在instrumentation API的帮助下,我可以控制类(并操纵它们)。使用普通Java,我可以估计每个对象使用的资源。到目前为止,一切都很好。
我现在面临的问题是“如何获取一个特定类的每个Object示例”。我可以通过字节码操作来获取对象示例,但我希望有另一个我不知道的API,帮助我完成我的目标,而不需要这样一个相当沉重的侵入步骤。最后,性能影响应该保持在最低限度。有什么想法吗?

aurhwmvo

aurhwmvo1#

Eclipse中的调试器可以使用show you all the instances of a class,所以我查看了Eclipse的源代码。Eclipse使用Java Debug Wire Protocol,它允许您(从Java 6开始)查找所请求类的所有示例。如果您想沿着这条路走下去,请获取Eclipse源代码的副本,并检查org.eclipse.jdi.internal.ReferenceTypeImplinstances方法。
一种更简单的方法是使用Java Debug Interface。请注意ReferenceType.instances方法。
我还没有弄清楚如何使用JDI连接到一个正在运行的进程,以及如何获得ReferenceType的示例。JDK包含了几个examples,所以我确信这是可行的。

9wbgstp7

9wbgstp72#

当我读到这篇文章的时候,我在想,既然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.
8ehkhllq

8ehkhllq3#

正如在其他答案中所解释的,您可以通过使用JDI协议来实现它。它相当简单:您需要使用以下命令在调试模式下运行JVM

--agentlib:jdwp=传输=dt_套接字,服务器=y,挂起=n,地址=56855

之后,你可以连接到远程(或本地JVM)并列出指定类的所有示例。2同样,你不能直接将远程对象转换为真实的对象,但是你可以访问远程对象的所有字段,甚至可以调用方法。
下面介绍如何连接到远程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和instances方法获取类的示例。它返回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。

6vl6ewon

6vl6ewon4#

http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html#IterateOverInstancesOfClass
你可以编写一些本地代码来获得JVMTI指针,然后使用它来迭代给定类的所有示例,如上面的链接所示。你可以从你的Java程序中调用这个本地代码。正如Eli所指出的,从Java6开始,有一个高级的 Package 器可以调用这个称为Java调试接口的接口。它允许您从Java本身进行这样的调用,而不必使用本地代码。
我希望这能有所帮助
冲压件

e1xvtsh3

e1xvtsh35#

我想知道您尝试做的事情是否可以使用BTrace来完成?

nkcskrwz

nkcskrwz6#

根据我在以前的文章中所了解到的,在Java中没有办法获得一个类的所有示例的列表。反射API做了一些很好的事情,但不是这个特定的事情。
你能做的最好的事情就是持有指向所有对象的指针,但这看起来很淫秽,而且对其他人的程序不起作用。不是很理想吧?

相关问题