src/jdk.jconsole/share/classes/sun/tools/jconsole/LocalVirtualMachine.java
changeset 47216 71c04702a3d5
parent 43494 11801b2ff456
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.tools.jconsole;
       
    27 
       
    28 import java.util.*;
       
    29 import java.io.IOException;
       
    30 import java.io.File;
       
    31 
       
    32 import com.sun.tools.attach.VirtualMachine;
       
    33 import com.sun.tools.attach.VirtualMachineDescriptor;
       
    34 import com.sun.tools.attach.AttachNotSupportedException;
       
    35 
       
    36 import jdk.internal.agent.ConnectorAddressLink;
       
    37 import sun.jvmstat.monitor.HostIdentifier;
       
    38 import sun.jvmstat.monitor.MonitoredHost;
       
    39 import sun.jvmstat.monitor.MonitoredVm;
       
    40 import sun.jvmstat.monitor.MonitoredVmUtil;
       
    41 import sun.jvmstat.monitor.MonitorException;
       
    42 import sun.jvmstat.monitor.VmIdentifier;
       
    43 
       
    44 public class LocalVirtualMachine {
       
    45     private String address;
       
    46     private String commandLine;
       
    47     private String displayName;
       
    48     private int vmid;
       
    49     private boolean isAttachSupported;
       
    50 
       
    51     public LocalVirtualMachine(int vmid, String commandLine, boolean canAttach, String connectorAddress) {
       
    52         this.vmid = vmid;
       
    53         this.commandLine = commandLine;
       
    54         this.address = connectorAddress;
       
    55         this.isAttachSupported = canAttach;
       
    56         this.displayName = getDisplayName(commandLine);
       
    57     }
       
    58 
       
    59     private static String getDisplayName(String commandLine) {
       
    60         // trim the pathname of jar file if it's a jar
       
    61         String[] res = commandLine.split(" ", 2);
       
    62         if (res[0].endsWith(".jar")) {
       
    63            File jarfile = new File(res[0]);
       
    64            String displayName = jarfile.getName();
       
    65            if (res.length == 2) {
       
    66                displayName += " " + res[1];
       
    67            }
       
    68            return displayName;
       
    69         }
       
    70         return commandLine;
       
    71     }
       
    72 
       
    73     public int vmid() {
       
    74         return vmid;
       
    75     }
       
    76 
       
    77     public boolean isManageable() {
       
    78         return (address != null);
       
    79     }
       
    80 
       
    81     public boolean isAttachable() {
       
    82         return isAttachSupported;
       
    83     }
       
    84 
       
    85     public void startManagementAgent() throws IOException {
       
    86         if (address != null) {
       
    87             // already started
       
    88             return;
       
    89         }
       
    90 
       
    91         if (!isAttachable()) {
       
    92             throw new IOException("This virtual machine \"" + vmid +
       
    93                 "\" does not support dynamic attach.");
       
    94         }
       
    95 
       
    96         loadManagementAgent();
       
    97         // fails to load or start the management agent
       
    98         if (address == null) {
       
    99             // should never reach here
       
   100             throw new IOException("Fails to find connector address");
       
   101         }
       
   102     }
       
   103 
       
   104     public String connectorAddress() {
       
   105         // return null if not available or no JMX agent
       
   106         return address;
       
   107     }
       
   108 
       
   109     public String displayName() {
       
   110         return displayName;
       
   111     }
       
   112 
       
   113     public String toString() {
       
   114         return commandLine;
       
   115     }
       
   116 
       
   117     // This method returns the list of all virtual machines currently
       
   118     // running on the machine
       
   119     public static Map<Integer, LocalVirtualMachine> getAllVirtualMachines() {
       
   120         Map<Integer, LocalVirtualMachine> map =
       
   121             new HashMap<Integer, LocalVirtualMachine>();
       
   122         getMonitoredVMs(map);
       
   123         getAttachableVMs(map);
       
   124         return map;
       
   125     }
       
   126 
       
   127     private static void getMonitoredVMs(Map<Integer, LocalVirtualMachine> map) {
       
   128         MonitoredHost host;
       
   129         Set<Integer> vms;
       
   130         try {
       
   131             host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null));
       
   132             vms = host.activeVms();
       
   133         } catch (java.net.URISyntaxException | MonitorException x) {
       
   134             throw new InternalError(x.getMessage(), x);
       
   135         }
       
   136         for (Object vmid: vms) {
       
   137             if (vmid instanceof Integer) {
       
   138                 int pid = ((Integer) vmid).intValue();
       
   139                 String name = vmid.toString(); // default to pid if name not available
       
   140                 boolean attachable = false;
       
   141                 String address = null;
       
   142                 try {
       
   143                      MonitoredVm mvm = host.getMonitoredVm(new VmIdentifier(name));
       
   144                      // use the command line as the display name
       
   145                      name =  MonitoredVmUtil.commandLine(mvm);
       
   146                      attachable = MonitoredVmUtil.isAttachable(mvm);
       
   147                      address = ConnectorAddressLink.importFrom(pid);
       
   148                      mvm.detach();
       
   149                 } catch (Exception x) {
       
   150                      // ignore
       
   151                 }
       
   152                 map.put((Integer) vmid,
       
   153                         new LocalVirtualMachine(pid, name, attachable, address));
       
   154             }
       
   155         }
       
   156     }
       
   157 
       
   158     private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
       
   159         "com.sun.management.jmxremote.localConnectorAddress";
       
   160 
       
   161     private static void getAttachableVMs(Map<Integer, LocalVirtualMachine> map) {
       
   162         List<VirtualMachineDescriptor> vms = VirtualMachine.list();
       
   163         for (VirtualMachineDescriptor vmd : vms) {
       
   164             try {
       
   165                 Integer vmid = Integer.valueOf(vmd.id());
       
   166                 if (!map.containsKey(vmid)) {
       
   167                     boolean attachable = false;
       
   168                     String address = null;
       
   169                     try {
       
   170                         VirtualMachine vm = VirtualMachine.attach(vmd);
       
   171                         attachable = true;
       
   172                         Properties agentProps = vm.getAgentProperties();
       
   173                         address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
       
   174                         vm.detach();
       
   175                     } catch (AttachNotSupportedException x) {
       
   176                         // not attachable
       
   177                     } catch (IOException x) {
       
   178                         // ignore
       
   179                     }
       
   180                     map.put(vmid, new LocalVirtualMachine(vmid.intValue(),
       
   181                                                           vmd.displayName(),
       
   182                                                           attachable,
       
   183                                                           address));
       
   184                 }
       
   185             } catch (NumberFormatException e) {
       
   186                 // do not support vmid different than pid
       
   187             }
       
   188         }
       
   189     }
       
   190 
       
   191     public static LocalVirtualMachine getLocalVirtualMachine(int vmid) {
       
   192         Map<Integer, LocalVirtualMachine> map = getAllVirtualMachines();
       
   193         LocalVirtualMachine lvm = map.get(vmid);
       
   194         if (lvm == null) {
       
   195             // Check if the VM is attachable but not included in the list
       
   196             // if it's running with a different security context.
       
   197             // For example, Windows services running
       
   198             // local SYSTEM account are attachable if you have Adminstrator
       
   199             // privileges.
       
   200             boolean attachable = false;
       
   201             String address = null;
       
   202             String name = String.valueOf(vmid); // default display name to pid
       
   203             try {
       
   204                 VirtualMachine vm = VirtualMachine.attach(name);
       
   205                 attachable = true;
       
   206                 Properties agentProps = vm.getAgentProperties();
       
   207                 address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
       
   208                 vm.detach();
       
   209                 lvm = new LocalVirtualMachine(vmid, name, attachable, address);
       
   210             } catch (AttachNotSupportedException x) {
       
   211                 // not attachable
       
   212                 if (JConsole.isDebug()) {
       
   213                     x.printStackTrace();
       
   214                 }
       
   215             } catch (IOException x) {
       
   216                 // ignore
       
   217                 if (JConsole.isDebug()) {
       
   218                     x.printStackTrace();
       
   219                 }
       
   220             }
       
   221         }
       
   222         return lvm;
       
   223     }
       
   224 
       
   225     // load the management agent into the target VM
       
   226     private void loadManagementAgent() throws IOException {
       
   227         VirtualMachine vm = null;
       
   228         String name = String.valueOf(vmid);
       
   229         try {
       
   230             vm = VirtualMachine.attach(name);
       
   231         } catch (AttachNotSupportedException x) {
       
   232             IOException ioe = new IOException(x.getMessage());
       
   233             ioe.initCause(x);
       
   234             throw ioe;
       
   235         }
       
   236 
       
   237         vm.startLocalManagementAgent();
       
   238 
       
   239         // get the connector address
       
   240         Properties agentProps = vm.getAgentProperties();
       
   241         address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
       
   242 
       
   243         vm.detach();
       
   244     }
       
   245 }