有没有一种简单的方法可以在 Java 中获取特定类的所有对象实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1947122/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a simple way of obtaining all object instances of a specific class in Java
提问by Mirko Jahn
Currently I am working on a Java agent to assemble memory stats. With the help of the instrumentation APII can get a hold of the classes (and manipulate them). With plain Java I can get an estimate of the resources used for each object. So far, so good.
目前我正在使用 Java 代理来组装内存统计信息。在检测 API的帮助下,我可以掌握这些类(并操纵它们)。使用普通的 Java,我可以估计每个对象使用的资源。到现在为止还挺好。
The question I am faced with right now is "how to get a hold of every Object instance of a specific class". I can do byte code manipulation in order to get a hold of the object instance, but I was hoping there is another API I am not aware of, helping me to accomplish my goal without such a rather heavy intrusive step. At the end, the performance impact should be kept to a minimum. Any ideas?
我现在面临的问题是“如何获取特定类的每个 Object 实例”。我可以进行字节码操作以获取对象实例,但我希望有另一个我不知道的 API,帮助我在没有如此繁重的侵入性步骤的情况下实现我的目标。最后,应将性能影响保持在最低限度。有任何想法吗?
回答by Eli Acherkan
The debugger in Eclipse can show you all the instances of a class, so I looked around Eclipse's sources. Eclipse uses the Java Debug Wire Protocol, which allows you (since Java 6) to look up all the instances of the requested class. If you want to go down this path, grab a copy of Eclipse sources and check out the instancesmethod of org.eclipse.jdi.internal.ReferenceTypeImpl.
Eclipse 中的调试器可以向您显示一个类的所有实例,因此我查看了 Eclipse 的源代码。Eclipse 使用Java Debug Wire Protocol,它允许您(自 Java 6 起)查找所请求类的所有实例。如果你想走上这条道路,抢的Eclipse的源副本,并检查出instances的方法org.eclipse.jdi.internal.ReferenceTypeImpl。
A simpler way is to use the Java Debug Interface. Note the ReferenceType.instancesmethod.
一种更简单的方法是使用Java 调试接口。注意ReferenceType.instances方法。
I still haven't figured out how to use JDI to connect to a running process and how to obtain an instance of ReferenceType. The JDK contains several examples, so I'm sure it's doable.
我还没有弄清楚如何使用 JDI 连接到正在运行的进程以及如何获取ReferenceType. JDK 包含几个示例,所以我确信它是可行的。
回答by danben
When I read this I was thinking that there must be SOME way to get this kind of info, since java profilers exist. Maybe this will help: http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html. It describes the interface between the JVM and a profiler agent. But if you were actually looking to write this in Java you may be out of luck.
当我读到这篇文章时,我在想一定有某种方法可以获取此类信息,因为存在 Java 分析器。也许这会有所帮助:http: //java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html。它描述了 JVM 和分析器代理之间的接口。但是如果你真的想用 Java 写这个,你可能不走运。
Specifically, check out this function:
具体来说,看看这个功能:
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.
回答by Ram
http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html#IterateOverInstancesOfClass
http://java.sun.com/j2se/1.5.0/docs/guide/jvmti/jvmti.html#IterateOverInstancesOfClass
You can write some native code that obtains the JVMTI pointer and then uses it to iterate over all instances of a given class as shown in the link above. You can call this native code from your Java program. As Eli points out though, there is a high level wrapper for this called Java Debug Interface available from Java 6 onwards, which allows you to make such calls from Java itself without having to muck around with native code.
您可以编写一些获取 JVMTI 指针的本机代码,然后使用它来迭代给定类的所有实例,如上面的链接所示。您可以从 Java 程序中调用此本机代码。不过,正如 Eli 指出的那样,从 Java 6 开始,这个称为 Java Debug Interface 的高级包装器可用,它允许您从 Java 本身进行此类调用,而无需处理本机代码。
hope this helps
希望这可以帮助
Ram
内存
回答by reidarok
回答by Dmitry.M
As explained in the other answers you can do it by using the JDI protocol. It is rather simple: you need to run the JVM in debug mode using
如其他答案中所述,您可以使用 JDI 协议来完成。这很简单:您需要使用以下命令在调试模式下运行 JVM
--agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=56855
--agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=56855
after that, you can connect to the remote (or local JVM) and list all instances of the specified class. Also, you cannot directly cast remote objects to the real object but you can access to all the fields of the remote object and even cal methods.
之后,您可以连接到远程(或本地 JVM)并列出指定类的所有实例。此外,您不能直接将远程对象转换为真实对象,但您可以访问远程对象的所有字段,甚至是 cal 方法。
Here how you can connect to remote JVM and get VirtualMachine.
此处介绍如何连接到远程 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);
}
After getting VirtualMachine you can get instances of a class using methods classesByName and instances. It return List of ReferenceType:
获得 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);
}
}
Here is a working exampleof a program than runs and connects to itself and list all instances of a java.lang.String. To run an example you need tool.jar from jdk in you classpath.
这是一个程序的工作示例,它运行并连接到自身并列出 java.lang.String 的所有实例。要运行示例,您需要在类路径中来自 jdk 的 tool.jar。
回答by Chuck Vose
From what I've been told in previous posts, there is no way to get a list of all the instances of a class in Java. The reflection API does some neat things but not this specific thing.
从我在之前的帖子中了解到的,没有办法在 Java 中获得一个类的所有实例的列表。反射 API 做了一些巧妙的事情,但不是这个特定的事情。
The best thing you can do is hold pointers to all objects but that seems obscene and doesn't work on other people's programs. Not ideal eh?
你能做的最好的事情是持有指向所有对象的指针,但这看起来很淫秽并且不适用于其他人的程序。不理想吧?

