001: /*
002: * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.jconsole;
027:
028: import java.util.*;
029: import java.io.IOException;
030: import java.io.File;
031:
032: // Sun specific
033: import com.sun.tools.attach.VirtualMachine;
034: import com.sun.tools.attach.VirtualMachineDescriptor;
035: import com.sun.tools.attach.AgentInitializationException;
036: import com.sun.tools.attach.AgentLoadException;
037: import com.sun.tools.attach.AttachNotSupportedException;
038:
039: // Sun private
040: import sun.management.ConnectorAddressLink;
041: import sun.jvmstat.monitor.HostIdentifier;
042: import sun.jvmstat.monitor.Monitor;
043: import sun.jvmstat.monitor.MonitoredHost;
044: import sun.jvmstat.monitor.MonitoredVm;
045: import sun.jvmstat.monitor.MonitoredVmUtil;
046: import sun.jvmstat.monitor.MonitorException;
047: import sun.jvmstat.monitor.VmIdentifier;
048:
049: public class LocalVirtualMachine {
050: private String address;
051: private String commandLine;
052: private String displayName;
053: private int vmid;
054: private boolean isAttachSupported;
055:
056: public LocalVirtualMachine(int vmid, String commandLine,
057: boolean canAttach, String connectorAddress) {
058: this .vmid = vmid;
059: this .commandLine = commandLine;
060: this .address = connectorAddress;
061: this .isAttachSupported = canAttach;
062: this .displayName = getDisplayName(commandLine);
063: }
064:
065: private static String getDisplayName(String commandLine) {
066: // trim the pathname of jar file if it's a jar
067: String[] res = commandLine.split(" ", 2);
068: if (res[0].endsWith(".jar")) {
069: File jarfile = new File(res[0]);
070: String displayName = jarfile.getName();
071: if (res.length == 2) {
072: displayName += " " + res[1];
073: }
074: return displayName;
075: }
076: return commandLine;
077: }
078:
079: public int vmid() {
080: return vmid;
081: }
082:
083: public boolean isManageable() {
084: return (address != null);
085: }
086:
087: public boolean isAttachable() {
088: return isAttachSupported;
089: }
090:
091: public void startManagementAgent() throws IOException {
092: if (address != null) {
093: // already started
094: return;
095: }
096:
097: if (!isAttachable()) {
098: throw new IOException("This virtual machine \"" + vmid
099: + "\" does not support dynamic attach.");
100: }
101:
102: loadManagementAgent();
103: // fails to load or start the management agent
104: if (address == null) {
105: // should never reach here
106: throw new IOException("Fails to find connector address");
107: }
108: }
109:
110: public String connectorAddress() {
111: // return null if not available or no JMX agent
112: return address;
113: }
114:
115: public String displayName() {
116: return displayName;
117: }
118:
119: public String toString() {
120: return commandLine;
121: }
122:
123: // This method returns the list of all virtual machines currently
124: // running on the machine
125: public static Map<Integer, LocalVirtualMachine> getAllVirtualMachines() {
126: Map<Integer, LocalVirtualMachine> map = new HashMap<Integer, LocalVirtualMachine>();
127: getMonitoredVMs(map);
128: getAttachableVMs(map);
129: return map;
130: }
131:
132: private static void getMonitoredVMs(
133: Map<Integer, LocalVirtualMachine> map) {
134: MonitoredHost host;
135: Set vms;
136: try {
137: host = MonitoredHost.getMonitoredHost(new HostIdentifier(
138: (String) null));
139: vms = host.activeVms();
140: } catch (java.net.URISyntaxException sx) {
141: throw new InternalError(sx.getMessage());
142: } catch (MonitorException mx) {
143: throw new InternalError(mx.getMessage());
144: }
145: for (Object vmid : vms) {
146: if (vmid instanceof Integer) {
147: int pid = ((Integer) vmid).intValue();
148: String name = vmid.toString(); // default to pid if name not available
149: boolean attachable = false;
150: String address = null;
151: try {
152: MonitoredVm mvm = host
153: .getMonitoredVm(new VmIdentifier(name));
154: // use the command line as the display name
155: name = MonitoredVmUtil.commandLine(mvm);
156: attachable = MonitoredVmUtil.isAttachable(mvm);
157: address = ConnectorAddressLink.importFrom(pid);
158: mvm.detach();
159: } catch (Exception x) {
160: // ignore
161: }
162: map.put((Integer) vmid, new LocalVirtualMachine(pid,
163: name, attachable, address));
164: }
165: }
166: }
167:
168: private static final String LOCAL_CONNECTOR_ADDRESS_PROP = "com.sun.management.jmxremote.localConnectorAddress";
169:
170: private static void getAttachableVMs(
171: Map<Integer, LocalVirtualMachine> map) {
172: List<VirtualMachineDescriptor> vms = VirtualMachine.list();
173: for (VirtualMachineDescriptor vmd : vms) {
174: try {
175: Integer vmid = Integer.valueOf(vmd.id());
176: if (!map.containsKey(vmid)) {
177: boolean attachable = false;
178: String address = null;
179: try {
180: VirtualMachine vm = VirtualMachine.attach(vmd);
181: attachable = true;
182: Properties agentProps = vm.getAgentProperties();
183: address = (String) agentProps
184: .get(LOCAL_CONNECTOR_ADDRESS_PROP);
185: vm.detach();
186: } catch (AttachNotSupportedException x) {
187: // not attachable
188: } catch (IOException x) {
189: // ignore
190: }
191: map.put(vmid, new LocalVirtualMachine(vmid
192: .intValue(), vmd.displayName(), attachable,
193: address));
194: }
195: } catch (NumberFormatException e) {
196: // do not support vmid different than pid
197: }
198: }
199: }
200:
201: public static LocalVirtualMachine getLocalVirtualMachine(int vmid) {
202: Map<Integer, LocalVirtualMachine> map = getAllVirtualMachines();
203: LocalVirtualMachine lvm = map.get(vmid);
204: if (lvm == null) {
205: // Check if the VM is attachable but not included in the list
206: // if it's running with a different security context.
207: // For example, Windows services running
208: // local SYSTEM account are attachable if you have Adminstrator
209: // privileges.
210: boolean attachable = false;
211: String address = null;
212: String name = String.valueOf(vmid); // default display name to pid
213: try {
214: VirtualMachine vm = VirtualMachine.attach(name);
215: attachable = true;
216: Properties agentProps = vm.getAgentProperties();
217: address = (String) agentProps
218: .get(LOCAL_CONNECTOR_ADDRESS_PROP);
219: vm.detach();
220: lvm = new LocalVirtualMachine(vmid, name, attachable,
221: address);
222: } catch (AttachNotSupportedException x) {
223: // not attachable
224: if (JConsole.isDebug()) {
225: x.printStackTrace();
226: }
227: } catch (IOException x) {
228: // ignore
229: if (JConsole.isDebug()) {
230: x.printStackTrace();
231: }
232: }
233: }
234: return lvm;
235: }
236:
237: // load the management agent into the target VM
238: private void loadManagementAgent() throws IOException {
239: VirtualMachine vm = null;
240: String name = String.valueOf(vmid);
241: try {
242: vm = VirtualMachine.attach(name);
243: } catch (AttachNotSupportedException x) {
244: IOException ioe = new IOException(x.getMessage());
245: ioe.initCause(x);
246: throw ioe;
247: }
248:
249: String home = vm.getSystemProperties().getProperty("java.home");
250:
251: // Normally in ${java.home}/jre/lib/management-agent.jar but might
252: // be in ${java.home}/lib in build environments.
253:
254: String agent = home + File.separator + "jre" + File.separator
255: + "lib" + File.separator + "management-agent.jar";
256: File f = new File(agent);
257: if (!f.exists()) {
258: agent = home + File.separator + "lib" + File.separator
259: + "management-agent.jar";
260: f = new File(agent);
261: if (!f.exists()) {
262: throw new IOException("Management agent not found");
263: }
264: }
265:
266: agent = f.getCanonicalPath();
267: try {
268: vm.loadAgent(agent, "com.sun.management.jmxremote");
269: } catch (AgentLoadException x) {
270: IOException ioe = new IOException(x.getMessage());
271: ioe.initCause(x);
272: throw ioe;
273: } catch (AgentInitializationException x) {
274: IOException ioe = new IOException(x.getMessage());
275: ioe.initCause(x);
276: throw ioe;
277: }
278:
279: // get the connector address
280: Properties agentProps = vm.getAgentProperties();
281: address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
282:
283: vm.detach();
284: }
285: }
|