3

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

4

1 回答 1

1

通常,要查找所有 jvm 进程,attach api 等于 jvmstat。但在某些定制的情况下,情况就不同了。不同的是 com.sun.tools.attach.spi.AttachProvider。

例如,在Windows 平台中,jvmstat 通过列出%TEMP%/hsperfdata_caoxudong 目录中的所有文件来查找java 进程(在linux 中为/tmp/hsperfdata_caoxudong)。并且 attach api 通过 AttachProvider 实例查找 java 进程。jdk 提供了一个默认的 AttachProvider 实现,这取决于您的操作系统平台。在 Windows 平台中,实现是 sun.tools.attach.WindowsAttachProvider。在它的 listVirtualMachines 方法中,如果 isTempPathSecure 方法返回 false,它将遍历所有进程,并找到所有加载库 "jvm.dll"的进程。您可以安装自己的 AttachProvider 实现以您自己的方式查找 java 进程,结果可能与 jvmstat 不同。AttachProvider 的安装在这里

于 2012-07-24T02:22:48.883 回答