正如其他答案中所解释的,您可以使用 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。