我正在编写一些与 JVM 实例相关的应用程序并查看开源以了解它是如何解决一些问题的。来自JDK7的 JConsole以两种方式收集正在运行的 VM(查看 GPL2 许可的源代码jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java
)。第一种是jvmstat方式,代码如下:
private static void getMonitoredVMs(Map<Integer, LocalVirtualMachine> map) {
MonitoredHost host;
Set vms;
try {
host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null));
vms = host.activeVms();
} catch (java.net.URISyntaxException sx) {
throw new InternalError(sx.getMessage());
} catch (MonitorException mx) {
throw new InternalError(mx.getMessage());
}
for (Object vmid: vms) {
if (vmid instanceof Integer) {
int pid = ((Integer) vmid).intValue();
String name = vmid.toString(); // default to pid if name not available
boolean attachable = false;
String address = null;
try {
MonitoredVm mvm = host.getMonitoredVm(new VmIdentifier(name));
// use the command line as the display name
name = MonitoredVmUtil.commandLine(mvm);
attachable = MonitoredVmUtil.isAttachable(mvm);
address = ConnectorAddressLink.importFrom(pid);
mvm.detach();
} catch (Exception x) {
// ignore
}
map.put((Integer) vmid,
new LocalVirtualMachine(pid, name, attachable, address));
}
}
}
其次是附加方式,如下所示:
private static void getAttachableVMs(Map<Integer, LocalVirtualMachine> map) {
List<VirtualMachineDescriptor> vms = VirtualMachine.list();
for (VirtualMachineDescriptor vmd : vms) {
try {
Integer vmid = Integer.valueOf(vmd.id());
if (!map.containsKey(vmid)) {
boolean attachable = false;
String address = null;
try {
VirtualMachine vm = VirtualMachine.attach(vmd);
attachable = true;
Properties agentProps = vm.getAgentProperties();
address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
vm.detach();
} catch (AttachNotSupportedException x) {
// not attachable
} catch (IOException x) {
// ignore
}
map.put(vmid, new LocalVirtualMachine(vmid.intValue(),
vmd.displayName(),
attachable,
address));
}
} catch (NumberFormatException e) {
// do not support vmid different than pid
}
}
}
我的问题:为什么它使用两种不同的工具来检索虚拟机列表?我知道通过附加 api,您只能列出由同一 JRE 运行的虚拟机,但 jvmstat 可以为您提供使用任何 JRE 版本运行的所有虚拟机的列表。我只测试了 JRE/JDK 7 32 位和 64 位,因为它们和更新版本是我的目标,遗憾的是仅在 Windows 上。仅使用 jvmstat 还不够吗?是否有任何情况下附加 api 可以看到某些 VM,但 jvmstat 看不到它?