1 /* 2 * Copyright (c) 2006, 2011, 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.io.File; 30 import java.io.IOException; 31 import java.io.InputStream; 32 33 import com.sun.tools.attach.VirtualMachine; 34 import sun.tools.attach.HotSpotVirtualMachine; 35 36 /* 37 * This class is the main class for the JInfo utility. It parses its arguments 38 * and decides if the command should be satisfied using the VM attach mechanism 39 * or an SA tool. At this time the only option that uses the VM attach 40 * mechanism is the -flag option to set or print a command line option of a 41 * running application. All other options are mapped to SA tools. 42 */ 43 public class JInfo { 44 45 public static void main(String[] args) throws Exception { 46 if (args.length == 0) { 47 usage(1); // no arguments 48 } 49 50 boolean useSA = true; 51 String arg1 = args[0]; 52 if (arg1.startsWith("-")) { 53 if (arg1.equals("-flags") || 54 arg1.equals("-sysprops")) { 55 // SA JInfo needs <pid> or <server> or 56 // (<executable> and <code file>). So, total 57 // argument count including option has to 2 or 3. 58 if (args.length != 2 && args.length != 3) { 59 usage(1); 60 } 61 } else if (arg1.equals("-flag")) { 62 // do not use SA, use attach-on-demand 63 useSA = false; 64 } else { 65 // unknown option or -h or -help, print help 66 int exit; 67 if (arg1.equals("-help") || arg1.equals("-h")) { 68 exit = 0; 69 } else { 70 exit = 1; 71 } 72 usage(exit); 73 } 74 } 75 76 if (useSA) { 77 runTool(args); 78 } else { 79 if (args.length == 3) { 80 String pid = args[2]; 81 String option = args[1]; 82 flag(pid, option); 83 } else { 84 int exit = arg1.equals("-help") || arg1.equals("-h") ? 0 : 1; 85 usage(exit); 86 } 87 } 88 } 89 90 // Invoke SA tool with the given arguments 91 private static void runTool(String args[]) throws Exception { 92 String tool = "sun.jvm.hotspot.tools.JInfo"; 93 // Tool not available on this platform. 94 Class<?> c = loadClass(tool); 95 if (c == null) { 96 usage(1); 97 } 98 99 // invoke the main method with the arguments 100 Class[] argTypes = { String[].class } ; 101 Method m = c.getDeclaredMethod("main", argTypes); 102 103 Object[] invokeArgs = { args }; 104 m.invoke(null, invokeArgs); 105 } 106 107 // loads the given class using the system class loader 108 private static Class<?> loadClass(String name) { 109 // 110 // We specify the system clas loader so as to cater for development 111 // environments where this class is on the boot class path but sa-jdi.jar 112 // is on the system class path. Once the JDK is deployed then both 113 // tools.jar and sa-jdi.jar are on the system class path. 114 // 115 try { 116 return Class.forName(name, true, 117 ClassLoader.getSystemClassLoader()); 118 } catch (Exception x) { } 119 return null; 120 } 121 122 private static void flag(String pid, String option) throws IOException { 123 VirtualMachine vm = attach(pid); 124 String flag; 125 InputStream in; 126 int index = option.indexOf('='); 127 if (index != -1) { 128 flag = option.substring(0, index); 129 String value = option.substring(index + 1); 130 in = ((HotSpotVirtualMachine)vm).setFlag(flag, value); 131 } else { 132 char c = option.charAt(0); 133 switch (c) { 134 case '+': 135 flag = option.substring(1); 136 in = ((HotSpotVirtualMachine)vm).setFlag(flag, "1"); 137 break; 138 case '-': 139 flag = option.substring(1); 140 in = ((HotSpotVirtualMachine)vm).setFlag(flag, "0"); 141 break; 142 default: 143 flag = option; 144 in = ((HotSpotVirtualMachine)vm).printFlag(flag); 145 break; 146 } 147 } 148 149 drain(vm, in); 150 } 151 152 // Attach to <pid>, exiting if we fail to attach 153 private static VirtualMachine attach(String pid) { 154 try { 155 return VirtualMachine.attach(pid); 156 } catch (Exception x) { 157 String msg = x.getMessage(); 158 if (msg != null) { 159 System.err.println(pid + ": " + msg); 160 } else { 161 x.printStackTrace(); 162 } 163 System.exit(1); 164 return null; // keep compiler happy 165 } 166 } 167 168 // Read the stream from the target VM until EOF, then detach 169 private static void drain(VirtualMachine vm, InputStream in) throws IOException { 170 // read to EOF and just print output 171 byte b[] = new byte[256]; 172 int n; 173 do { 174 n = in.read(b); 175 if (n > 0) { 176 String s = new String(b, 0, n, "UTF-8"); 177 System.out.print(s); 178 } 179 } while (n > 0); 180 in.close(); 181 vm.detach(); 182 } 183 184 185 // print usage message 186 private static void usage(int exit) { 187 188 Class<?> c = loadClass("sun.jvm.hotspot.tools.JInfo"); 189 boolean usageSA = (c != null); 190 191 System.err.println("Usage:"); 192 if (usageSA) { 193 System.err.println(" jinfo [option] <pid>"); 194 System.err.println(" (to connect to running process)"); 195 System.err.println(" jinfo [option] <executable <core>"); 196 System.err.println(" (to connect to a core file)"); 197 System.err.println(" jinfo [option] [server_id@]<remote server IP or hostname>"); 198 System.err.println(" (to connect to remote debug server)"); 199 System.err.println(""); 200 System.err.println("where <option> is one of:"); 201 System.err.println(" -flag <name> to print the value of the named VM flag"); 202 System.err.println(" -flag [+|-]<name> to enable or disable the named VM flag"); 203 System.err.println(" -flag <name>=<value> to set the named VM flag to the given value"); 204 System.err.println(" -flags to print VM flags"); 205 System.err.println(" -sysprops to print Java system properties"); 206 System.err.println(" <no option> to print both of the above"); 207 System.err.println(" -h | -help to print this help message"); 208 } else { 209 System.err.println(" jinfo <option> <pid>"); 210 System.err.println(" (to connect to a running process)"); 211 System.err.println(""); 212 System.err.println("where <option> is one of:"); 213 System.err.println(" -flag <name> to print the value of the named VM flag"); 214 System.err.println(" -flag [+|-]<name> to enable or disable the named VM flag"); 215 System.err.println(" -flag <name>=<value> to set the named VM flag to the given value"); 216 System.err.println(" -h | -help to print this help message"); 217 } 218 219 System.exit(exit); 220 } 221 }