JInfo.java revision 10444:f08705540498
1/* 2 * Copyright (c) 2006, 2014, 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 26package sun.tools.jinfo; 27 28import java.lang.reflect.Method; 29import java.util.Arrays; 30import java.io.IOException; 31import java.io.InputStream; 32 33import com.sun.tools.attach.VirtualMachine; 34 35import sun.tools.attach.HotSpotVirtualMachine; 36 37/* 38 * This class is the main class for the JInfo utility. It parses its arguments 39 * and decides if the command should be satisfied using the VM attach mechanism 40 * or an SA tool. 41 */ 42final public class JInfo { 43 private boolean useSA = false; 44 private String[] args = null; 45 46 private JInfo(String[] args) throws IllegalArgumentException { 47 if (args.length == 0) { 48 throw new IllegalArgumentException(); 49 } 50 51 int argCopyIndex = 0; 52 // First determine if we should launch SA or not 53 if (args[0].equals("-F")) { 54 // delete the -F 55 argCopyIndex = 1; 56 useSA = true; 57 } else if (args[0].equals("-flags") 58 || args[0].equals("-sysprops")) 59 { 60 if (args.length == 2) { 61 if (!isPid(args[1])) { 62 // If args[1] doesn't parse to a number then 63 // it must be the SA debug server 64 // (otherwise it is the pid) 65 useSA = true; 66 } 67 } else if (args.length == 3) { 68 // arguments include an executable and a core file 69 useSA = true; 70 } else { 71 throw new IllegalArgumentException(); 72 } 73 } else if (!args[0].startsWith("-")) { 74 if (args.length == 2) { 75 // the only arguments are an executable and a core file 76 useSA = true; 77 } else if (args.length == 1) { 78 if (!isPid(args[0])) { 79 // The only argument is not a PID; it must be SA debug 80 // server 81 useSA = true; 82 } 83 } else { 84 throw new IllegalArgumentException(); 85 } 86 } else if (args[0].equals("-h") || args[0].equals("-help")) { 87 if (args.length > 1) { 88 throw new IllegalArgumentException(); 89 } 90 } else if (args[0].equals("-flag")) { 91 if (args.length == 3) { 92 if (!isPid(args[2])) { 93 throw new IllegalArgumentException(); 94 } 95 } else { 96 throw new IllegalArgumentException(); 97 } 98 } else { 99 throw new IllegalArgumentException(); 100 } 101 102 this.args = Arrays.copyOfRange(args, argCopyIndex, args.length); 103 } 104 105 @SuppressWarnings("fallthrough") 106 private void execute() throws Exception { 107 if (args[0].equals("-h") 108 || args[0].equals("-help")) { 109 usage(0); 110 } 111 112 if (useSA) { 113 // SA only supports -flags or -sysprops 114 if (args[0].startsWith("-")) { 115 if (!(args[0].equals("-flags") || args[0].equals("-sysprops"))) { 116 usage(1); 117 } 118 } 119 120 // invoke SA which does it's own argument parsing 121 runTool(); 122 123 } else { 124 // Now we can parse arguments for the non-SA case 125 String pid = null; 126 127 switch(args[0]) { 128 case "-flag": 129 if (args.length != 3) { 130 usage(1); 131 } 132 String option = args[1]; 133 pid = args[2]; 134 flag(pid, option); 135 break; 136 case "-flags": 137 if (args.length != 2) { 138 usage(1); 139 } 140 pid = args[1]; 141 flags(pid); 142 break; 143 case "-sysprops": 144 if (args.length != 2) { 145 usage(1); 146 } 147 pid = args[1]; 148 sysprops(pid); 149 break; 150 case "-help": 151 case "-h": 152 usage(0); 153 // Fall through 154 default: 155 if (args.length == 1) { 156 // no flags specified, we do -sysprops and -flags 157 pid = args[0]; 158 sysprops(pid); 159 System.out.println(); 160 flags(pid); 161 System.out.println(); 162 commandLine(pid); 163 } else { 164 usage(1); 165 } 166 } 167 } 168 } 169 170 public static void main(String[] args) throws Exception { 171 JInfo jinfo = null; 172 try { 173 jinfo = new JInfo(args); 174 jinfo.execute(); 175 } catch (IllegalArgumentException e) { 176 usage(1); 177 } 178 } 179 180 private static boolean isPid(String arg) { 181 return arg.matches("[0-9]+"); 182 } 183 184 // Invoke SA tool with the given arguments 185 private void runTool() throws Exception { 186 String tool = "sun.jvm.hotspot.tools.JInfo"; 187 // Tool not available on this platform. 188 Class<?> c = loadClass(tool); 189 if (c == null) { 190 usage(1); 191 } 192 193 // invoke the main method with the arguments 194 Class<?>[] argTypes = { String[].class } ; 195 Method m = c.getDeclaredMethod("main", argTypes); 196 197 Object[] invokeArgs = { args }; 198 m.invoke(null, invokeArgs); 199 } 200 201 // loads the given class using the system class loader 202 private static Class<?> loadClass(String name) { 203 // 204 // We specify the system class loader so as to cater for development 205 // environments where this class is on the boot class path but sa-jdi.jar 206 // is on the system class path. Once the JDK is deployed then both 207 // tools.jar and sa-jdi.jar are on the system class path. 208 // 209 try { 210 return Class.forName(name, true, 211 ClassLoader.getSystemClassLoader()); 212 } catch (Exception x) { } 213 return null; 214 } 215 216 private static void flag(String pid, String option) throws IOException { 217 HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid); 218 String flag; 219 InputStream in; 220 int index = option.indexOf('='); 221 if (index != -1) { 222 flag = option.substring(0, index); 223 String value = option.substring(index + 1); 224 in = vm.setFlag(flag, value); 225 } else { 226 char c = option.charAt(0); 227 switch (c) { 228 case '+': 229 flag = option.substring(1); 230 in = vm.setFlag(flag, "1"); 231 break; 232 case '-': 233 flag = option.substring(1); 234 in = vm.setFlag(flag, "0"); 235 break; 236 default: 237 flag = option; 238 in = vm.printFlag(flag); 239 break; 240 } 241 } 242 243 drain(vm, in); 244 } 245 246 private static void flags(String pid) throws IOException { 247 HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid); 248 InputStream in = vm.executeJCmd("VM.flags"); 249 System.out.println("VM Flags:"); 250 drain(vm, in); 251 } 252 253 private static void commandLine(String pid) throws IOException { 254 HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid); 255 InputStream in = vm.executeJCmd("VM.command_line"); 256 drain(vm, in); 257 } 258 259 private static void sysprops(String pid) throws IOException { 260 HotSpotVirtualMachine vm = (HotSpotVirtualMachine) attach(pid); 261 InputStream in = vm.executeJCmd("VM.system_properties"); 262 System.out.println("Java System Properties:"); 263 drain(vm, in); 264 } 265 266 // Attach to <pid>, exiting if we fail to attach 267 private static VirtualMachine attach(String pid) { 268 try { 269 return VirtualMachine.attach(pid); 270 } catch (Exception x) { 271 String msg = x.getMessage(); 272 if (msg != null) { 273 System.err.println(pid + ": " + msg); 274 } else { 275 x.printStackTrace(); 276 } 277 System.exit(1); 278 return null; // keep compiler happy 279 } 280 } 281 282 // Read the stream from the target VM until EOF, then detach 283 private static void drain(VirtualMachine vm, InputStream in) throws IOException { 284 // read to EOF and just print output 285 byte b[] = new byte[256]; 286 int n; 287 do { 288 n = in.read(b); 289 if (n > 0) { 290 String s = new String(b, 0, n, "UTF-8"); 291 System.out.print(s); 292 } 293 } while (n > 0); 294 in.close(); 295 vm.detach(); 296 } 297 298 299 // print usage message 300 private static void usage(int exit) { 301 302 Class<?> c = loadClass("sun.jvm.hotspot.tools.JInfo"); 303 boolean usageSA = (c != null); 304 305 System.err.println("Usage:"); 306 if (usageSA) { 307 System.err.println(" jinfo [option] <pid>"); 308 System.err.println(" (to connect to a running process)"); 309 System.err.println(" jinfo -F [option] <pid>"); 310 System.err.println(" (to connect to a hung process)"); 311 System.err.println(" jinfo [option] <executable> <core>"); 312 System.err.println(" (to connect to a core file)"); 313 System.err.println(" jinfo [option] [server_id@]<remote server IP or hostname>"); 314 System.err.println(" (to connect to remote debug server)"); 315 System.err.println(""); 316 System.err.println("where <option> is one of:"); 317 System.err.println(" for running processes:"); 318 System.err.println(" -flag <name> to print the value of the named VM flag"); 319 System.err.println(" -flag [+|-]<name> to enable or disable the named VM flag"); 320 System.err.println(" -flag <name>=<value> to set the named VM flag to the given value"); 321 System.err.println(" for running or hung processes and core files:"); 322 System.err.println(" -flags to print VM flags"); 323 System.err.println(" -sysprops to print Java system properties"); 324 System.err.println(" <no option> to print both VM flags and system properties"); 325 System.err.println(" -h | -help to print this help message"); 326 } else { 327 System.err.println(" jinfo <option> <pid>"); 328 System.err.println(" (to connect to a running process)"); 329 System.err.println(""); 330 System.err.println("where <option> is one of:"); 331 System.err.println(" -flag <name> to print the value of the named VM flag"); 332 System.err.println(" -flag [+|-]<name> to enable or disable the named VM flag"); 333 System.err.println(" -flag <name>=<value> to set the named VM flag to the given value"); 334 System.err.println(" -flags to print VM flags"); 335 System.err.println(" -sysprops to print Java system properties"); 336 System.err.println(" <no option> to print both VM flags and system properties"); 337 System.err.println(" -h | -help to print this help message"); 338 } 339 340 System.exit(exit); 341 } 342} 343