1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 *com.sun.tools.attach.AttachNotSupportedException 5 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package sun.tools.jcmd; 28 29 import java.io.InputStream; 30 import java.io.IOException; 31 import java.io.UnsupportedEncodingException; 32 import java.util.List; 33 import java.util.ArrayList; 34 import java.util.Comparator; 35 import java.net.URISyntaxException; 36 37 import com.sun.tools.attach.VirtualMachine; 38 import com.sun.tools.attach.VirtualMachineDescriptor; 39 import com.sun.tools.attach.AgentLoadException; 40 import com.sun.tools.attach.AttachNotSupportedException; 41 import sun.tools.attach.HotSpotVirtualMachine; 42 import sun.tools.jstat.JStatLogger; 43 import sun.jvmstat.monitor.Monitor; 44 import sun.jvmstat.monitor.MonitoredHost; 45 import sun.jvmstat.monitor.MonitoredVm; 46 import sun.jvmstat.monitor.MonitoredVmUtil; 47 import sun.jvmstat.monitor.MonitorException; 48 import sun.jvmstat.monitor.VmIdentifier; 49 50 public class JCmd { 51 public static void main(String[] args) { 52 Arguments arg = null; 53 try { 54 arg = new Arguments(args); 55 } catch (IllegalArgumentException ex) { 56 System.err.println("Error parsing arguments: " + ex.getMessage() 57 + "\n"); 58 Arguments.usage(); 59 System.exit(1); 60 } 61 62 if (arg.isShowUsage()) { 63 Arguments.usage(); 64 System.exit(1); 65 } 66 67 if (arg.isListProcesses()) { 68 List<VirtualMachineDescriptor> vmds = VirtualMachine.list(); 69 for (VirtualMachineDescriptor vmd : vmds) { 70 System.out.println(vmd.id() + " " + vmd.displayName()); 71 } 72 System.exit(0); 73 } 74 75 List<String> pids = new ArrayList<String>(); 76 if (arg.getPid() == 0) { 77 // find all VMs 78 List<VirtualMachineDescriptor> vmds = VirtualMachine.list(); 79 for (VirtualMachineDescriptor vmd : vmds) { 80 if (!isJCmdProcess(vmd)) { 81 pids.add(vmd.id()); 82 } 83 } 84 } else if (arg.getProcessSubstring() != null) { 85 // use the partial class-name match 86 List<VirtualMachineDescriptor> vmds = VirtualMachine.list(); 87 for (VirtualMachineDescriptor vmd : vmds) { 88 if (isJCmdProcess(vmd)) { 89 continue; 90 } 91 try { 92 String mainClass = getMainClass(vmd); 93 if (mainClass != null 94 && mainClass.indexOf(arg.getProcessSubstring()) != -1) { 95 pids.add(vmd.id()); 96 } 97 } catch (MonitorException|URISyntaxException e) { 98 if (e.getMessage() != null) { 99 System.err.println(e.getMessage()); 100 } else { 101 Throwable cause = e.getCause(); 102 if ((cause != null) && (cause.getMessage() != null)) { 103 System.err.println(cause.getMessage()); 104 } else { 105 e.printStackTrace(); 106 } 107 } 108 } 109 } 110 if (pids.isEmpty()) { 111 System.err.println("Could not find any processes matching : '" 112 + arg.getProcessSubstring() + "'"); 113 System.exit(1); 114 } 115 } else if (arg.getPid() == -1) { 116 System.err.println("Invalid pid specified"); 117 System.exit(1); 118 } else { 119 // Use the found pid 120 pids.add(arg.getPid() + ""); 121 } 122 123 for (String pid : pids) { 124 System.out.println(pid + ":"); 125 if (arg.isListCounters()) { 126 listCounters(pid); 127 } else { 128 try { 129 executeCommandForPid(pid, arg.getCommand()); 130 } catch(Exception ex) { 131 ex.printStackTrace(); 132 } 133 } 134 } 135 } 136 137 private static void executeCommandForPid(String pid, String command) 138 throws AttachNotSupportedException, IOException, 139 UnsupportedEncodingException { 140 VirtualMachine vm = VirtualMachine.attach(pid); 141 142 // Cast to HotSpotVirtualMachine as this is an 143 // implementation specific method. 144 HotSpotVirtualMachine hvm = (HotSpotVirtualMachine) vm; 145 try (InputStream in = hvm.executeJCmd(command);) { 146 // read to EOF and just print output 147 byte b[] = new byte[256]; 148 int n; 149 do { 150 n = in.read(b); 151 if (n > 0) { 152 String s = new String(b, 0, n, "UTF-8"); 153 System.out.print(s); 154 } 155 } while (n > 0); 156 } 157 vm.detach(); 158 } 159 160 private static void listCounters(String pid) { 161 // Code from JStat (can't call it directly since it does System.exit) 162 VmIdentifier vmId = null; 163 try { 164 vmId = new VmIdentifier(pid); 165 } catch (URISyntaxException e) { 166 System.err.println("Malformed VM Identifier: " + pid); 167 return; 168 } 169 try { 170 MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId); 171 MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1); 172 JStatLogger logger = new JStatLogger(monitoredVm); 173 logger.printSnapShot("\\w*", // all names 174 new AscendingMonitorComparator(), // comparator 175 false, // not verbose 176 true, // show unsupported 177 System.out); 178 monitoredHost.detach(monitoredVm); 179 } catch (MonitorException ex) { 180 ex.printStackTrace(); 181 } 182 } 183 184 private static boolean isJCmdProcess(VirtualMachineDescriptor vmd) { 185 try { 186 String mainClass = getMainClass(vmd); 187 return mainClass != null && mainClass.equals(JCmd.class.getName()); 188 } catch (URISyntaxException|MonitorException ex) { 189 return false; 190 } 191 } 192 193 private static String getMainClass(VirtualMachineDescriptor vmd) 194 throws URISyntaxException, MonitorException { 195 try { 196 String mainClass = null; 197 VmIdentifier vmId = new VmIdentifier(vmd.id()); 198 MonitoredHost monitoredHost = MonitoredHost.getMonitoredHost(vmId); 199 MonitoredVm monitoredVm = monitoredHost.getMonitoredVm(vmId, -1); 200 mainClass = MonitoredVmUtil.mainClass(monitoredVm, true); 201 monitoredHost.detach(monitoredVm); 202 return mainClass; 203 } catch(NullPointerException e) { 204 // There is a potential race, where a running java app is being 205 // queried, unfortunately the java app has shutdown after this 206 // method is started but before getMonitoredVM is called. 207 // If this is the case, then the /tmp/hsperfdata_xxx/pid file 208 // will have disappeared and we will get a NullPointerException. 209 // Handle this gracefully.... 210 return null; 211 } 212 } 213 214 /** 215 * Class to compare two Monitor objects by name in ascending order. 216 * (from jstat) 217 */ 218 static class AscendingMonitorComparator implements Comparator<Monitor> { 219 220 public int compare(Monitor m1, Monitor m2) { 221 String name1 = m1.getName(); 222 String name2 = m2.getName(); 223 return name1.compareTo(name2); 224 } 225 } 226 }