我正在编写一些与JVM实例相关的应用程序并查看开源,看看它是如何解决一些问题的。来自JDK7的JConsole以两种方式收集正在运行的VM(查看jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java
中由GPL2许可的源)。第一个是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
}
}
}
我的问题:为什么它使用两种不同的工具来检索虚拟机列表?我知道通过attach api你可以列出由同一个JRE运行的虚拟机,但jvmstat可以列出所有运行任何JRE版本的虚拟机。我已经测试了JRE / JDK 7 32和64位,因为它们和我的目标是我的目标,遗憾的是只在Windows上。仅仅使用jvmstat是不够的?是否有任何情况通过附加api可见某些VM,但是jvmstat看不到它?
答案 0 :(得分:1)
通常,为了查找所有jvm进程,attach api等于jvmstat。但在一些定制的情况下,它是不同的。不同的是com.sun.tools.attach.spi.AttachProvider。
e.g。在Windows平台上,jvmstat通过列出目录%TEMP%/ hsperfdata_caoxudong中的所有文件找到java进程(在linux中,它是/ tmp / hsperfdata_caoxudong)。并附加api通过AttachProvider实例找到java进程。 jdk提供了一个默认的AttachProvider实现,它取决于您的操作系统平台。在Windows平台中,实现是sun.tools.attach.WindowsAttachProvider。在其listVirtualMachines方法中,如果isTempPathSecure方法返回false,它将迭代所有进程,并find all processes, which loaded library "jvm.dll"。您可以安装自己的AttachProvider实现,以自己的方式查找Java进程,结果可能与jvmstat不同。 AttachProvider的安装是here。