2012-06-23 32 views
3

我正在寫一些JVM實例相關的應用程序,並看着開源,看看它是如何解決一些問題。 JDK7的JConsole以兩種方式收集正在運行的VM(請查看jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java中的GPL2許可的源代碼)。首先是jvmstat的方式,這樣的代碼:爲什麼JDK的JConsole尋找使用jvmstat和attach api的虛擬機?

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運行的VM,但是jvmstat可以爲您提供使用任何JRE版本運行的所有VM的列表。我已經測試過JRE/JDK 7 32和64位,只是因爲他們和更新是我的目標,不幸的是只在Windows上。僅僅使用jvmstat是不夠的?是否有任何情況下,通過attach api可以看到某個VM,但jvmstat無法看到它?

回答

1

通常,查找所有jvm進程時,附加api等於jvmstat。但在一些定製的情況下,它是不同的。而不同的是com.sun.tools.attach.spi.AttachProvider。

例如在Windows平臺上,jvmstat通過列出目錄%TEMP%/ hsperfdata_caoxudong(在Linux中,它是/ tmp/hsperfdata_caoxudong)中的所有文件來查找java進程。並附上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