001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.jps;
042:
043: import java.lang.reflect.InvocationTargetException;
044: import java.lang.reflect.Method;
045: import org.netbeans.lib.profiler.global.CommonConstants;
046: import org.netbeans.lib.profiler.global.Platform;
047: import org.netbeans.lib.profiler.utils.MiscUtils;
048: import sun.jvmstat.monitor.*;
049: import java.lang.management.ManagementFactory;
050: import java.net.URISyntaxException;
051: import java.util.ArrayList;
052: import java.util.Iterator;
053: import java.util.List;
054: import java.util.Set;
055:
056: /**
057: * This class is based on "jvmps" class from jvmps 2.0 written by Brian Doherty.
058: * It provides functionality to identify all the JVMs currently running on the local machine.
059: * Comments starting with //// are original comments from Brian.
060: *
061: * @author Tomas Hurka
062: * @author Misha Dmitriev
063: */
064: public class JpsProxy {
065:
066: //~ Methods ------------------------------------------------------------------------------------------------------------------
067:
068: /** Returns the array of records for all running VMs capable of dynaimic attach (JDK 1.6 and newer)*/
069: public static RunningVM[] getRunningVMs() {
070: String hostname = null;
071: List vret = new ArrayList();
072:
073: try {
074: HostIdentifier hostId = new HostIdentifier(hostname);
075: MonitoredHost monitoredHost = MonitoredHost
076: .getMonitoredHost(hostId);
077: String selfName = ManagementFactory.getRuntimeMXBean()
078: .getName();
079:
080: //// get the list active VMs on the specified host.
081: Set jvms = monitoredHost.activeVms();
082:
083: if (jvms.isEmpty()) {
084: return null;
085: }
086:
087: for (Iterator j = jvms.iterator(); j.hasNext();) {
088: int lvmid = ((Integer) j.next()).intValue();
089:
090: if (selfName.startsWith(lvmid + "@")) { // myself
091:
092: continue;
093: }
094:
095: VmIdentifier id = null;
096: MonitoredVm vm = null;
097: String uriString = "//" + lvmid + "?mode=r"; // NOI18N
098:
099: try {
100: id = new VmIdentifier(uriString);
101: vm = monitoredHost.getMonitoredVm(id, 0);
102: } catch (URISyntaxException e) {
103: //// this error should not occur as we are creating our own VMIdentifiers above based on a validated HostIdentifier.
104: //// This would be an unexpected condition.
105: MiscUtils
106: .printWarningMessage("in jvmps, detected malformed VM Identifier: "
107: + uriString + "; ignored"); // NOI18N
108:
109: continue;
110: } catch (MonitorException e) {
111: System.out.println("Ex " + e.getMessage());
112: e.printStackTrace();
113:
114: //// it's possible that from the time we acquired the list of available jvms that a jvm has terminated. Therefore, it is
115: //// best just to ignore this error.
116: continue;
117: } catch (Exception e) {
118: //// certain types of errors, such as access acceptions, can be encountered when attaching to a jvm.
119: //// These are reported as exceptions, not as some subclass of security exception.
120:
121: //// FIXME - we should probably have some provision for logging these types of errors, or possibly just print out the
122: //// the Java Virtual Machine lvmid in a finally clause: System.out.println(String.valueOf(lvmid));
123: MiscUtils.printWarningMessage("in jvmps, for VM = "
124: + String.valueOf(lvmid)
125: + " got exception: " + e); // NOI18N
126:
127: continue;
128: }
129:
130: if (!isAttachable(vm)) {
131: monitoredHost.detach(vm);
132:
133: continue;
134: }
135:
136: String cmdString = MonitoredVmUtil.commandLine(vm);
137: String mainClass = MonitoredVmUtil.mainClass(vm, true);
138: String mainArgs = MonitoredVmUtil.mainArgs(vm);
139: String vmArgs = MonitoredVmUtil.jvmArgs(vm);
140: String vmFlags = MonitoredVmUtil.jvmFlags(vm);
141:
142: monitoredHost.detach(vm);
143:
144: RunningVM rvm = new RunningVM(lvmid, vmFlags, vmArgs,
145: mainClass, mainArgs);
146: vret.add(rvm);
147: }
148: } catch (MonitorException e) {
149: String report = "in jvmps, got MonitorException"; // NOI18N
150:
151: if (e.getMessage() != null) {
152: report += (" with message + " + e.getMessage()); // NOI18N
153: }
154:
155: MiscUtils.printWarningMessage(report);
156:
157: return null;
158: } catch (URISyntaxException e) {
159: MiscUtils
160: .printWarningMessage("in jvmps, got malformed Host Identifier: "
161: + hostname); // NOI18N
162:
163: return null;
164: }
165:
166: return (RunningVM[]) vret.toArray(new RunningVM[vret.size()]);
167: }
168:
169: // invoke MonitoredVmUtil.isAttachable(MonitoredVm vm) using reflection (JDK 6 only code)
170: private static Method monitoredVmUtil_isAttachable;
171:
172: static {
173: try {
174: monitoredVmUtil_isAttachable = MonitoredVmUtil.class
175: .getMethod("isAttachable",
176: new Class[] { MonitoredVm.class }); // NOI18N
177: } catch (SecurityException ex) {
178: ex.printStackTrace();
179: } catch (NoSuchMethodException ex) {
180: ex.printStackTrace();
181: }
182: }
183:
184: private static boolean isAttachable(MonitoredVm vm) {
185: Object ret;
186: try {
187: ret = monitoredVmUtil_isAttachable.invoke(null,
188: new Object[] { vm });
189: if (ret instanceof Boolean) {
190: return ((Boolean) ret).booleanValue();
191: }
192: } catch (IllegalArgumentException ex) {
193: ex.printStackTrace();
194: } catch (IllegalAccessException ex) {
195: ex.printStackTrace();
196: } catch (InvocationTargetException ex) {
197: ex.printStackTrace();
198: }
199: return false;
200: }
201: }
|