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(); // 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(); 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 usage(); 67 } 68 } 69 70 if (useSA) { 71 runTool(args); 72 } else { 73 if (args.length == 3) { 74 String pid = args[2]; 75 String option = args[1]; 76 flag(pid, option); 77 } else { 78 usage(); 79 } 80 } 81 } 82 83 // Invoke SA tool with the given arguments 84 private static void runTool(String args[]) throws Exception { 85 String tool = "sun.jvm.hotspot.tools.JInfo"; 86 // Tool not available on this platform. 87 Class<?> c = loadClass(tool); 88 if (c == null) { 89 usage(); 90 } 91 92 // invoke the main method with the arguments 93 Class[] argTypes = { String[].class } ; 94 Method m = c.getDeclaredMethod("main", argTypes); 95 96 Object[] invokeArgs = { args }; 97 m.invoke(null, invokeArgs); 98 } 99 100 // loads the given class using the system class loader 101 private static Class<?> loadClass(String name) { 102 // 103 // We specify the system clas loader so as to cater for development 104 // environments where this class is on the boot class path but sa-jdi.jar 105 // is on the system class path. Once the JDK is deployed then both 106 // tools.jar and sa-jdi.jar are on the system class path. 107 // 108 try { 109 return Class.forName(name, true, 110 ClassLoader.getSystemClassLoader()); 111 } catch (Exception x) { } 112 return null; 113 } 114 115 private static void flag(String pid, String option) throws IOException { 116 VirtualMachine vm = attach(pid); 117 String flag; 118 InputStream in; 119 int index = option.indexOf('='); 120 if (index != -1) { 121 flag = option.substring(0, index); 122 String value = option.substring(index + 1); 123 in = ((HotSpotVirtualMachine)vm).setFlag(flag, value); 124 } else { 125 char c = option.charAt(0); 126 switch (c) { 127 case '+': 128 flag = option.substring(1); 129 in = ((HotSpotVirtualMachine)vm).setFlag(flag, "1"); 130 break; 131 case '-': 132 flag = option.substring(1); 133 in = ((HotSpotVirtualMachine)vm).setFlag(flag, "0"); 134 break; 135 default: 136 flag = option; 137 in = ((HotSpotVirtualMachine)vm).printFlag(flag); 138 break; 139 } 140 } 141 142 drain(vm, in); 143 } 144 145 // Attach to <pid>, exiting if we fail to attach 146 private static VirtualMachine attach(String pid) { 147 try { 148 return VirtualMachine.attach(pid); 149 } catch (Exception x) { 150 String msg = x.getMessage(); 151 if (msg != null) { 152 System.err.println(pid + ": " + msg); 153 } else { 154 x.printStackTrace(); 155 } 156 System.exit(1); 157 return null; // keep compiler happy 158 } 159 } 160 161 // Read the stream from the target VM until EOF, then detach 162 private static void drain(VirtualMachine vm, InputStream in) throws IOException { 163 // read to EOF and just print output 164 byte b[] = new byte[256]; 165 int n; 166 do { 167 n = in.read(b); 168 if (n > 0) { 169 String s = new String(b, 0, n, "UTF-8"); 170 System.out.print(s); 171 } 172 } while (n > 0); 173 in.close(); 174 vm.detach(); 175 } 176 177 178 // print usage message 179 private static void usage() { 180 181 Class<?> c = loadClass("sun.jvm.hotspot.tools.JInfo"); 182 boolean usageSA = (c != null); 183 184 System.out.println("Usage:"); 185 if (usageSA) { 186 System.out.println(" jinfo [option] <pid>"); 187 System.out.println(" (to connect to running process)"); 188 System.out.println(" jinfo [option] <executable <core>"); 189 System.out.println(" (to connect to a core file)"); 190 System.out.println(" jinfo [option] [server_id@]<remote server IP or hostname>"); 191 System.out.println(" (to connect to remote debug server)"); 192 System.out.println(""); 193 System.out.println("where <option> is one of:"); 194 System.out.println(" -flag <name> to print the value of the named VM flag"); 195 System.out.println(" -flag [+|-]<name> to enable or disable the named VM flag"); 196 System.out.println(" -flag <name>=<value> to set the named VM flag to the given value"); 197 System.out.println(" -flags to print VM flags"); 198 System.out.println(" -sysprops to print Java system properties"); 199 System.out.println(" <no option> to print both of the above"); 200 System.out.println(" -h | -help to print this help message"); 201 } else { 202 System.out.println(" jinfo <option> <pid>"); 203 System.out.println(" (to connect to a running process)"); 204 System.out.println(""); 205 System.out.println("where <option> is one of:"); 206 System.out.println(" -flag <name> to print the value of the named VM flag"); 207 System.out.println(" -flag [+|-]<name> to enable or disable the named VM flag"); 208 System.out.println(" -flag <name>=<value> to set the named VM flag to the given value"); 209 System.out.println(" -h | -help to print this help message"); 210 } 211 212 System.exit(1); 213 } 214 }