Showing the changes to java/pkg/sun/tools/jconsole/LocalVirtualMachine.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,280 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2005, 2006, 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 | // Sun specific | ||
| 33 | import com.sun.tools.attach.VirtualMachine; | ||
| 34 | import com.sun.tools.attach.VirtualMachineDescriptor; | ||
| 35 | import com.sun.tools.attach.AgentInitializationException; | ||
| 36 | import com.sun.tools.attach.AgentLoadException; | ||
| 37 | import com.sun.tools.attach.AttachNotSupportedException; | ||
| 38 | |||
| 39 | // Sun private | ||
| 40 | import sun.management.ConnectorAddressLink; | ||
| 41 | import sun.jvmstat.monitor.HostIdentifier; | ||
| 42 | import sun.jvmstat.monitor.Monitor; | ||
| 43 | import sun.jvmstat.monitor.MonitoredHost; | ||
| 44 | import sun.jvmstat.monitor.MonitoredVm; | ||
| 45 | import sun.jvmstat.monitor.MonitoredVmUtil; | ||
| 46 | import sun.jvmstat.monitor.MonitorException; | ||
| 47 | import sun.jvmstat.monitor.VmIdentifier; | ||
| 48 | |||
| 49 | public class LocalVirtualMachine { | ||
| 50 | private String address; | ||
| 51 | private String commandLine; | ||
| 52 | private String displayName; | ||
| 53 | private int vmid; | ||
| 54 | private boolean isAttachSupported; | ||
| 55 | |||
| 56 | public LocalVirtualMachine(int vmid, String commandLine, boolean canAttach, String connectorAddress) { | ||
| 57 | this.vmid = vmid; | ||
| 58 | this.commandLine = commandLine; | ||
| 59 | this.address = connectorAddress; | ||
| 60 | this.isAttachSupported = canAttach; | ||
| 61 | this.displayName = getDisplayName(commandLine); | ||
| 62 | } | ||
| 63 | |||
| 64 | private static String getDisplayName(String commandLine) { | ||
| 65 | // trim the pathname of jar file if it's a jar | ||
| 66 | String[] res = commandLine.split(" ", 2); | ||
| 67 | if (res[0].endsWith(".jar")) { | ||
| 68 | File jarfile = new File(res[0]); | ||
| 69 | String displayName = jarfile.getName(); | ||
| 70 | if (res.length == 2) { | ||
| 71 | displayName += " " + res[1]; | ||
| 72 | } | ||
| 73 | return displayName; | ||
| 74 | } | ||
| 75 | return commandLine; | ||
| 76 | } | ||
| 77 | |||
| 78 | public int vmid() { | ||
| 79 | return vmid; | ||
| 80 | } | ||
| 81 | |||
| 82 | public boolean isManageable() { | ||
| 83 | return (address != null); | ||
| 84 | } | ||
| 85 | |||
| 86 | public boolean isAttachable() { | ||
| 87 | return isAttachSupported; | ||
| 88 | } | ||
| 89 | |||
| 90 | public void startManagementAgent() throws IOException { | ||
| 91 | if (address != null) { | ||
| 92 | // already started | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (!isAttachable()) { | ||
| 97 | throw new IOException("This virtual machine \"" + vmid + | ||
| 98 | "\" does not support dynamic attach."); | ||
| 99 | } | ||
| 100 | |||
| 101 | loadManagementAgent(); | ||
| 102 | // fails to load or start the management agent | ||
| 103 | if (address == null) { | ||
| 104 | // should never reach here | ||
| 105 | throw new IOException("Fails to find connector address"); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | public String connectorAddress() { | ||
| 110 | // return null if not available or no JMX agent | ||
| 111 | return address; | ||
| 112 | } | ||
| 113 | |||
| 114 | public String displayName() { | ||
| 115 | return displayName; | ||
| 116 | } | ||
| 117 | |||
| 118 | public String toString() { | ||
| 119 | return commandLine; | ||
| 120 | } | ||
| 121 | |||
| 122 | // This method returns the list of all virtual machines currently | ||
| 123 | // running on the machine | ||
| 124 | public static Map<Integer, LocalVirtualMachine> getAllVirtualMachines() { | ||
| 125 | Map<Integer, LocalVirtualMachine> map = | ||
| 126 | new HashMap<Integer, LocalVirtualMachine>(); | ||
| 127 | getMonitoredVMs(map); | ||
| 128 | getAttachableVMs(map); | ||
| 129 | return map; | ||
| 130 | } | ||
| 131 | |||
| 132 | private static void getMonitoredVMs(Map<Integer, LocalVirtualMachine> map) { | ||
| 133 | MonitoredHost host; | ||
| 134 | Set vms; | ||
| 135 | try { | ||
| 136 | host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null)); | ||
| 137 | vms = host.activeVms(); | ||
| 138 | } catch (java.net.URISyntaxException sx) { | ||
| 139 | throw new InternalError(sx.getMessage()); | ||
| 140 | } catch (MonitorException mx) { | ||
| 141 | throw new InternalError(mx.getMessage()); | ||
| 142 | } | ||
| 143 | for (Object vmid: vms) { | ||
| 144 | if (vmid instanceof Integer) { | ||
| 145 | int pid = ((Integer) vmid).intValue(); | ||
| 146 | String name = vmid.toString(); // default to pid if name not available | ||
| 147 | boolean attachable = false; | ||
| 148 | String address = null; | ||
| 149 | try { | ||
| 150 | MonitoredVm mvm = host.getMonitoredVm(new VmIdentifier(name)); | ||
| 151 | // use the command line as the display name | ||
| 152 | name = MonitoredVmUtil.commandLine(mvm); | ||
| 153 | attachable = MonitoredVmUtil.isAttachable(mvm); | ||
| 154 | address = ConnectorAddressLink.importFrom(pid); | ||
| 155 | mvm.detach(); | ||
| 156 | } catch (Exception x) { | ||
| 157 | // ignore | ||
| 158 | } | ||
| 159 | map.put((Integer) vmid, | ||
| 160 | new LocalVirtualMachine(pid, name, attachable, address)); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | private static final String LOCAL_CONNECTOR_ADDRESS_PROP = | ||
| 166 | "com.sun.management.jmxremote.localConnectorAddress"; | ||
| 167 | |||
| 168 | private static void getAttachableVMs(Map<Integer, LocalVirtualMachine> map) { | ||
| 169 | List<VirtualMachineDescriptor> vms = VirtualMachine.list(); | ||
| 170 | for (VirtualMachineDescriptor vmd : vms) { | ||
| 171 | try { | ||
| 172 | Integer vmid = Integer.valueOf(vmd.id()); | ||
| 173 | if (!map.containsKey(vmid)) { | ||
| 174 | boolean attachable = false; | ||
| 175 | String address = null; | ||
| 176 | try { | ||
| 177 | VirtualMachine vm = VirtualMachine.attach(vmd); | ||
| 178 | attachable = true; | ||
| 179 | Properties agentProps = vm.getAgentProperties(); | ||
| 180 | address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP); | ||
| 181 | vm.detach(); | ||
| 182 | } catch (AttachNotSupportedException x) { | ||
| 183 | // not attachable | ||
| 184 | } catch (IOException x) { | ||
| 185 | // ignore | ||
| 186 | } | ||
| 187 | map.put(vmid, new LocalVirtualMachine(vmid.intValue(), | ||
| 188 | vmd.displayName(), | ||
| 189 | attachable, | ||
| 190 | address)); | ||
| 191 | } | ||
| 192 | } catch (NumberFormatException e) { | ||
| 193 | // do not support vmid different than pid | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | public static LocalVirtualMachine getLocalVirtualMachine(int vmid) { | ||
| 199 | Map<Integer, LocalVirtualMachine> map = getAllVirtualMachines(); | ||
| 200 | LocalVirtualMachine lvm = map.get(vmid); | ||
| 201 | if (lvm == null) { | ||
| 202 | // Check if the VM is attachable but not included in the list | ||
| 203 | // if it's running with a different security context. | ||
| 204 | // For example, Windows services running | ||
| 205 | // local SYSTEM account are attachable if you have Adminstrator | ||
| 206 | // privileges. | ||
| 207 | boolean attachable = false; | ||
| 208 | String address = null; | ||
| 209 | String name = String.valueOf(vmid); // default display name to pid | ||
| 210 | try { | ||
| 211 | VirtualMachine vm = VirtualMachine.attach(name); | ||
| 212 | attachable = true; | ||
| 213 | Properties agentProps = vm.getAgentProperties(); | ||
| 214 | address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP); | ||
| 215 | vm.detach(); | ||
| 216 | lvm = new LocalVirtualMachine(vmid, name, attachable, address); | ||
| 217 | } catch (AttachNotSupportedException x) { | ||
| 218 | // not attachable | ||
| 219 | if (JConsole.isDebug()) { | ||
| 220 | x.printStackTrace(); | ||
| 221 | } | ||
| 222 | } catch (IOException x) { | ||
| 223 | // ignore | ||
| 224 | if (JConsole.isDebug()) { | ||
| 225 | x.printStackTrace(); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | } | ||
| 229 | return lvm; | ||
| 230 | } | ||
| 231 | |||
| 232 | // load the management agent into the target VM | ||
| 233 | private void loadManagementAgent() throws IOException { | ||
| 234 | VirtualMachine vm = null; | ||
| 235 | String name = String.valueOf(vmid); | ||
| 236 | try { | ||
| 237 | vm = VirtualMachine.attach(name); | ||
| 238 | } catch (AttachNotSupportedException x) { | ||
| 239 | IOException ioe = new IOException(x.getMessage()); | ||
| 240 | ioe.initCause(x); | ||
| 241 | throw ioe; | ||
| 242 | } | ||
| 243 | |||
| 244 | String home = vm.getSystemProperties().getProperty("java.home"); | ||
| 245 | |||
| 246 | // Normally in ${java.home}/jre/lib/management-agent.jar but might | ||
| 247 | // be in ${java.home}/lib in build environments. | ||
| 248 | |||
| 249 | String agent = home + File.separator + "jre" + File.separator + | ||
| 250 | "lib" + File.separator + "management-agent.jar"; | ||
| 251 | File f = new File(agent); | ||
| 252 | if (!f.exists()) { | ||
| 253 | agent = home + File.separator + "lib" + File.separator + | ||
| 254 | "management-agent.jar"; | ||
| 255 | f = new File(agent); | ||
| 256 | if (!f.exists()) { | ||
| 257 | throw new IOException("Management agent not found"); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | agent = f.getCanonicalPath(); | ||
| 262 | try { | ||
| 263 | vm.loadAgent(agent, "com.sun.management.jmxremote"); | ||
| 264 | } catch (AgentLoadException x) { | ||
| 265 | IOException ioe = new IOException(x.getMessage()); | ||
| 266 | ioe.initCause(x); | ||
| 267 | throw ioe; | ||
| 268 | } catch (AgentInitializationException x) { | ||
| 269 | IOException ioe = new IOException(x.getMessage()); | ||
| 270 | ioe.initCause(x); | ||
| 271 | throw ioe; | ||
| 272 | } | ||
| 273 | |||
| 274 | // get the connector address | ||
| 275 | Properties agentProps = vm.getAgentProperties(); | ||
| 276 | address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP); | ||
| 277 | |||
| 278 | vm.detach(); | ||
| 279 | } | ||
| 280 | } | ||