Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有一种简单的方法可以获取Java中特定类的所有对象实例_Java_Jvm_Profiling - Fatal编程技术网

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

有没有一种简单的方法可以获取Java中特定类的所有对象实例,java,jvm,profiling,Java,Jvm,Profiling,目前我正在开发一个Java代理来组装内存统计数据。在的帮助下,我可以掌握类(并操纵它们)。使用纯Java,我可以估计每个对象使用的资源。到目前为止,一切顺利 我现在面临的问题是“如何获取特定类的每个对象实例”。为了获得对象实例,我可以进行字节码操作,但我希望有另一个我不知道的API,可以帮助我完成目标,而无需进行如此繁重的侵入性步骤。最后,性能影响应保持在最低限度。有什么想法吗?根据我在以前的帖子中所听到的,没有办法获得Java中类的所有实例的列表。反射API做了一些简单的事情,但没有做这个具体

目前我正在开发一个Java代理来组装内存统计数据。在的帮助下,我可以掌握类(并操纵它们)。使用纯Java,我可以估计每个对象使用的资源。到目前为止,一切顺利


我现在面临的问题是“如何获取特定类的每个对象实例”。为了获得对象实例,我可以进行字节码操作,但我希望有另一个我不知道的API,可以帮助我完成目标,而无需进行如此繁重的侵入性步骤。最后,性能影响应保持在最低限度。有什么想法吗?

根据我在以前的帖子中所听到的,没有办法获得Java中类的所有实例的列表。反射API做了一些简单的事情,但没有做这个具体的事情


你能做的最好的事情就是持有指向所有对象的指针,但这看起来很淫秽,而且对其他人的程序不起作用。不理想,嗯?

当我读到这篇文章时,我想一定有某种方法可以获取此类信息,因为java分析器已经存在。也许这会有帮助。它描述了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. 

Eclipse中的调试器可以,所以我查看了Eclipse的源代码。Eclipse使用,这允许您(从Java6开始)查找所请求类的所有实例。如果您想沿着这条路走下去,请获取Eclipse源代码的副本,并查看
org.Eclipse.jdi.internal.ReferenceTypeImpl
instances
方法

更简单的方法是使用。注意方法

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

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

希望这有帮助


Ram

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

如其他答案中所述,您可以通过使用JDI协议来完成。这相当简单:您需要在调试模式下使用

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

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

这里介绍如何连接到远程JVM并获取

private static VirtualMachine attach(字符串主机名、字符串端口)引发IOException、IllegalConnectorArgumentsException{
//使用套接字连接到其他JVM的getSocketAttaching连接器
AttachingConnector connector=Bootstrap.virtualMachineManager().attachingConnectors()
.stream().filter(p->p.transport().name().contains(“套接字”))
.findFirst().get();
//设置连接器的参数
Map arg=connector.defaultArguments();
arg.get(“主机名”).setValue(主机名);
参数get(“端口”).setValue(端口);
//通过套接字连接到远程进程
返回连接器。连接(arg);
}
获取VirtualMachine后,您可以使用方法classesByName和instances获取类的实例。它返回的列表包括:

VirtualMachine vm=attach(“localhost”,“56856”);
//获取java.lang.String的所有类。只有一个元素。
List classes=vm.classesByName(“java.lang.String”);
//获取类的所有实例(设置要获取的最大实例数)。
List o=classes.get(0).instances(100000);
//objectReference保留对远程对象的引用。
for(ObjectReference ObjectReference:o){
试一试{
//显示远程对象的文本表示形式
System.out.println(objectReference.toString());
}catch(com.sun.jdi.ObjectCollectedException e){
//指定的对象已被垃圾回收
//要避免这种情况,请使用vm.suspend()vm.resume()
系统输出打印ln(e);
}
}

下面是程序运行和连接到自身的示例,并列出java.lang.String的所有实例。要运行一个示例,您需要在类路径中使用jdk中的tool.jar。

如果使用WeakReferences()来保存指针,那么它实际上并不是那么淫秽。JVMPI已经被JVMTI()所取代,但是+1用于实际读取OP并使用工具接口进行响应
    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 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);
            }
        }