blob: 6611711bee57afb5ce5462d87377c999b4c4cfe0 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.tools.jconsole;
27
28import java.util.*;
29import java.io.IOException;
30import java.io.File;
31
32// Sun specific
33import com.sun.tools.attach.VirtualMachine;
34import com.sun.tools.attach.VirtualMachineDescriptor;
35import com.sun.tools.attach.AgentInitializationException;
36import com.sun.tools.attach.AgentLoadException;
37import com.sun.tools.attach.AttachNotSupportedException;
38
39// Sun private
40import sun.management.ConnectorAddressLink;
41import sun.jvmstat.monitor.HostIdentifier;
42import sun.jvmstat.monitor.Monitor;
43import sun.jvmstat.monitor.MonitoredHost;
44import sun.jvmstat.monitor.MonitoredVm;
45import sun.jvmstat.monitor.MonitoredVmUtil;
46import sun.jvmstat.monitor.MonitorException;
47import sun.jvmstat.monitor.VmIdentifier;
48
49public 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}