为什么JDK的JConsole使用jvmstat和attach api来寻找虚拟机?

时间:2012-06-23 15:04:58

标签: java jvm openjdk

我正在编写一些与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看不到它?

1 个答案:

答案 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