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