1 /* 2 * Copyright (c) 2015, 2016, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 package sun.jvm.hotspot; 26 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 30 import sun.jvm.hotspot.tools.JStack; 31 import sun.jvm.hotspot.tools.JMap; 32 import sun.jvm.hotspot.tools.JInfo; 33 import sun.jvm.hotspot.tools.JSnap; 34 35 public class SALauncher { 36 37 private static boolean launcherHelp() { 38 System.out.println(" clhsdb \tcommand line debugger"); 39 System.out.println(" debugd \tdebug server"); 40 System.out.println(" hsdb \tui debugger"); 41 System.out.println(" jstack --help\tto get more information"); 42 System.out.println(" jmap --help\tto get more information"); 43 System.out.println(" jinfo --help\tto get more information"); 44 System.out.println(" jsnap --help\tto get more information"); 45 return false; 46 } 47 48 private static boolean commonHelp() { 49 // --pid <pid> 50 // --exe <exe> 51 // --core <core> 52 System.out.println(" --exe\texecutable image name"); 53 System.out.println(" --core\tpath to coredump"); 54 System.out.println(" --pid\tpid of process to attach"); 55 return false; 56 } 57 58 private static boolean debugdHelp() { 59 // [options] <pid> [server-id] 60 // [options] <executable> <core> [server-id] 61 java.io.PrintStream out = System.out; 62 out.print(" [option] <pid> [server-id]"); 63 out.println("\t\t(to connect to a live java process)"); 64 out.print(" or [option] <executable> <core> [server-id]"); 65 out.println("\t\t(to connect to a core file produced by <executable>)"); 66 out.print("\t\tserver-id is an optional unique id for this debug server, needed "); 67 out.println("\t\tif multiple debug servers are run on the same machine"); 68 out.println("where option includes:"); 69 out.println(" -h | -help\tto print this help message"); 70 return false; 71 } 72 73 private static boolean jinfoHelp() { 74 // --flags -> -flags 75 // --sysprops -> -sysprops 76 System.out.println(" --flags\tto print VM flags"); 77 System.out.println(" --sysprops\tto print Java System properties"); 78 System.out.println(" <no option>\tto print both of the above"); 79 return commonHelp(); 80 } 81 82 private static boolean jmapHelp() { 83 // --heap -> -heap 84 // --binaryheap -> -heap:format=b 85 // --histo -> -histo 86 // --clstats -> -clstats 87 // --finalizerinfo -> -finalizerinfo 88 89 System.out.println(" <no option>\tto print same info as Solaris pmap"); 90 System.out.println(" --heap\tto print java heap summary"); 91 System.out.println(" --binaryheap\tto dump java heap in hprof binary format"); 92 System.out.println(" --dumpfile\tname of the dump file"); 93 System.out.println(" --histo\tto print histogram of java object heap"); 94 System.out.println(" --clstats\tto print class loader statistics"); 95 System.out.println(" --finalizerinfo\tto print information on objects awaiting finalization"); 96 return commonHelp(); 97 } 98 99 private static boolean jstackHelp() { 100 // --locks -> -l 101 // --mixed -> -m 102 System.out.println(" --locks\tto print java.util.concurrent locks"); 103 System.out.println(" --mixed\tto print both java and native frames (mixed mode)"); 104 return commonHelp(); 105 } 106 107 private static boolean jsnapHelp() { 108 System.out.println(" --all\tto print all performance counters"); 109 return commonHelp(); 110 } 111 112 private static boolean toolHelp(String toolName) { 113 if (toolName.equals("jstack")) { 114 return jstackHelp(); 115 } 116 if (toolName.equals("jinfo")) { 117 return jinfoHelp(); 118 } 119 if (toolName.equals("jmap")) { 120 return jmapHelp(); 121 } 122 if (toolName.equals("jsnap")) { 123 return jsnapHelp(); 124 } 125 if (toolName.equals("debugd")) { 126 return debugdHelp(); 127 } 128 if (toolName.equals("hsdb") || toolName.equals("clhsdb")) { 129 return commonHelp(); 130 } 131 return launcherHelp(); 132 } 133 134 private static void buildAttachArgs(ArrayList<String> newArgs, String pid, 135 String exe, String core, boolean allowEmpty) { 136 if (!allowEmpty && (pid == null) && (exe == null)) { 137 throw new SAGetoptException("You have to set --pid or --exe."); 138 } 139 140 if (pid != null) { // Attach to live process 141 if (exe != null) { 142 throw new SAGetoptException("Unnecessary argument: --exe"); 143 } else if (core != null) { 144 throw new SAGetoptException("Unnecessary argument: --core"); 145 } else if (!pid.matches("^\\d+$")) { 146 throw new SAGetoptException("Invalid pid: " + pid); 147 } 148 149 newArgs.add(pid); 150 } else if (exe != null) { 151 if (exe.length() == 0) { 152 throw new SAGetoptException("You have to set --exe."); 153 } 154 155 newArgs.add(exe); 156 157 if ((core == null) || (core.length() == 0)) { 158 throw new SAGetoptException("You have to set --core."); 159 } 160 161 newArgs.add(core); 162 } 163 } 164 165 private static void runCLHSDB(String[] oldArgs) { 166 SAGetopt sg = new SAGetopt(oldArgs); 167 String[] longOpts = {"exe=", "core=", "pid="}; 168 169 ArrayList<String> newArgs = new ArrayList(); 170 String pid = null; 171 String exe = null; 172 String core = null; 173 String s = null; 174 175 while((s = sg.next(null, longOpts)) != null) { 176 if (s.equals("exe")) { 177 exe = sg.getOptarg(); 178 continue; 179 } 180 if (s.equals("core")) { 181 core = sg.getOptarg(); 182 continue; 183 } 184 if (s.equals("pid")) { 185 pid = sg.getOptarg(); 186 continue; 187 } 188 } 189 190 buildAttachArgs(newArgs, pid, exe, core, true); 191 CLHSDB.main(newArgs.toArray(new String[newArgs.size()])); 192 } 193 194 private static void runHSDB(String[] oldArgs) { 195 SAGetopt sg = new SAGetopt(oldArgs); 196 String[] longOpts = {"exe=", "core=", "pid="}; 197 198 ArrayList<String> newArgs = new ArrayList(); 199 String pid = null; 200 String exe = null; 201 String core = null; 202 String s = null; 203 204 while((s = sg.next(null, longOpts)) != null) { 205 if (s.equals("exe")) { 206 exe = sg.getOptarg(); 207 continue; 208 } 209 if (s.equals("core")) { 210 core = sg.getOptarg(); 211 continue; 212 } 213 if (s.equals("pid")) { 214 pid = sg.getOptarg(); 215 continue; 216 } 217 } 218 219 buildAttachArgs(newArgs, pid, exe, core, true); 220 HSDB.main(newArgs.toArray(new String[newArgs.size()])); 221 } 222 223 private static void runJSTACK(String[] oldArgs) { 224 SAGetopt sg = new SAGetopt(oldArgs); 225 String[] longOpts = {"exe=", "core=", "pid=", 226 "mixed", "locks"}; 227 228 ArrayList<String> newArgs = new ArrayList(); 229 String pid = null; 230 String exe = null; 231 String core = null; 232 String s = null; 233 234 while((s = sg.next(null, longOpts)) != null) { 235 if (s.equals("exe")) { 236 exe = sg.getOptarg(); 237 continue; 238 } 239 if (s.equals("core")) { 240 core = sg.getOptarg(); 241 continue; 242 } 243 if (s.equals("pid")) { 244 pid = sg.getOptarg(); 245 continue; 246 } 247 if (s.equals("mixed")) { 248 newArgs.add("-m"); 249 continue; 250 } 251 if (s.equals("locks")) { 252 newArgs.add("-l"); 253 continue; 254 } 255 } 256 257 buildAttachArgs(newArgs, pid, exe, core, false); 258 JStack jstack = new JStack(false, false); 259 jstack.runWithArgs(newArgs.toArray(new String[newArgs.size()])); 260 } 261 262 private static void runJMAP(String[] oldArgs) { 263 SAGetopt sg = new SAGetopt(oldArgs); 264 String[] longOpts = {"exe=", "core=", "pid=", 265 "heap", "binaryheap", "dumpfile=", "histo", "clstats", "finalizerinfo"}; 266 267 ArrayList<String> newArgs = new ArrayList(); 268 String pid = null; 269 String exe = null; 270 String core = null; 271 String s = null; 272 String dumpfile = null; 273 boolean requestHeapdump = false; 274 275 while((s = sg.next(null, longOpts)) != null) { 276 if (s.equals("exe")) { 277 exe = sg.getOptarg(); 278 continue; 279 } 280 if (s.equals("core")) { 281 core = sg.getOptarg(); 282 continue; 283 } 284 if (s.equals("pid")) { 285 pid = sg.getOptarg(); 286 continue; 287 } 288 if (s.equals("heap")) { 289 newArgs.add("-heap"); 290 continue; 291 } 292 if (s.equals("binaryheap")) { 293 requestHeapdump = true; 294 continue; 295 } 296 if (s.equals("dumpfile")) { 297 dumpfile = sg.getOptarg(); 298 continue; 299 } 300 if (s.equals("histo")) { 301 newArgs.add("-histo"); 302 continue; 303 } 304 if (s.equals("clstats")) { 305 newArgs.add("-clstats"); 306 continue; 307 } 308 if (s.equals("finalizerinfo")) { 309 newArgs.add("-finalizerinfo"); 310 continue; 311 } 312 } 313 314 if (!requestHeapdump && (dumpfile != null)) { 315 throw new IllegalArgumentException("Unexpected argument dumpfile"); 316 } 317 if (requestHeapdump) { 318 if (dumpfile == null) { 319 newArgs.add("-heap:format=b"); 320 } else { 321 newArgs.add("-heap:format=b,file=" + dumpfile); 322 } 323 } 324 325 buildAttachArgs(newArgs, pid, exe, core, false); 326 JMap.main(newArgs.toArray(new String[newArgs.size()])); 327 } 328 329 private static void runJINFO(String[] oldArgs) { 330 SAGetopt sg = new SAGetopt(oldArgs); 331 String[] longOpts = {"exe=", "core=", "pid=", 332 "flags", "sysprops"}; 333 334 ArrayList<String> newArgs = new ArrayList(); 335 String exe = null; 336 String pid = null; 337 String core = null; 338 String s = null; 339 340 while((s = sg.next(null, longOpts)) != null) { 341 if (s.equals("exe")) { 342 exe = sg.getOptarg(); 343 continue; 344 } 345 if (s.equals("core")) { 346 core = sg.getOptarg(); 347 continue; 348 } 349 if (s.equals("pid")) { 350 pid = sg.getOptarg(); 351 continue; 352 } 353 if (s.equals("flags")) { 354 newArgs.add("-flags"); 355 continue; 356 } 357 if (s.equals("sysprops")) { 358 newArgs.add("-sysprops"); 359 continue; 360 } 361 } 362 363 buildAttachArgs(newArgs, pid, exe, core, false); 364 JInfo.main(newArgs.toArray(new String[newArgs.size()])); 365 } 366 367 private static void runJSNAP(String[] oldArgs) { 368 SAGetopt sg = new SAGetopt(oldArgs); 369 String[] longOpts = {"exe=", "core=", "pid=", "all"}; 370 371 ArrayList<String> newArgs = new ArrayList(); 372 String exe = null; 373 String pid = null; 374 String core = null; 375 String s = null; 376 377 while((s = sg.next(null, longOpts)) != null) { 378 if (s.equals("exe")) { 379 exe = sg.getOptarg(); 380 continue; 381 } 382 if (s.equals("core")) { 383 core = sg.getOptarg(); 384 continue; 385 } 386 if (s.equals("pid")) { 387 pid = sg.getOptarg(); 388 continue; 389 } 390 if (s.equals("all")) { 391 newArgs.add("-a"); 392 continue; 393 } 394 } 395 396 buildAttachArgs(newArgs, pid, exe, core, false); 397 JSnap.main(newArgs.toArray(new String[newArgs.size()])); 398 } 399 400 private static void runDEBUGD(String[] oldArgs) { 401 if ((oldArgs.length < 1) || (oldArgs.length > 3)) { 402 debugdHelp(); 403 } 404 405 // By default SA agent classes prefer Windows process debugger 406 // to windbg debugger. SA expects special properties to be set 407 // to choose other debuggers. We will set those here before 408 // attaching to SA agent. 409 System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true"); 410 411 // delegate to the actual SA debug server. 412 sun.jvm.hotspot.DebugServer.main(oldArgs); 413 } 414 415 public static void main(String[] args) { 416 // Provide a help 417 if (args.length == 0) { 418 launcherHelp(); 419 return; 420 } 421 // No arguments imply help for debugd, jstack, jmap, jinfo but launch clhsdb and hsdb 422 if (args.length == 1 && !args[0].equals("clhsdb") && !args[0].equals("hsdb")) { 423 toolHelp(args[0]); 424 return; 425 } 426 427 for (String arg : args) { 428 if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")) { 429 toolHelp(args[0]); 430 return; 431 } 432 } 433 434 String[] oldArgs = Arrays.copyOfRange(args, 1, args.length); 435 436 try { 437 // Run SA interactive mode 438 if (args[0].equals("clhsdb")) { 439 runCLHSDB(oldArgs); 440 return; 441 } 442 443 if (args[0].equals("hsdb")) { 444 runHSDB(oldArgs); 445 return; 446 } 447 448 // Run SA tmtools mode 449 if (args[0].equals("jstack")) { 450 runJSTACK(oldArgs); 451 return; 452 } 453 454 if (args[0].equals("jmap")) { 455 runJMAP(oldArgs); 456 return; 457 } 458 459 if (args[0].equals("jinfo")) { 460 runJINFO(oldArgs); 461 return; 462 } 463 464 if (args[0].equals("jsnap")) { 465 runJSNAP(oldArgs); 466 return; 467 } 468 469 if (args[0].equals("debugd")) { 470 runDEBUGD(oldArgs); 471 return; 472 } 473 474 throw new SAGetoptException("Unknown tool: " + args[0]); 475 } catch (SAGetoptException e) { 476 System.err.println(e.getMessage()); 477 toolHelp(args[0]); 478 } 479 } 480 }