1 /* 2 * Copyright (c) 2015, 2019, 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(" hsdb \tui debugger"); 40 System.out.println(" debugd --help\tto get more information"); 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(String mode) { 49 // --pid <pid> 50 // --exe <exe> 51 // --core <core> 52 System.out.println(" --pid <pid> \tTo attach to and operate on the given live process."); 53 System.out.println(" --core <corefile>\tTo operate on the given core file."); 54 System.out.println(" --exe <executable for corefile>"); 55 System.out.println(); 56 System.out.println(" The --core and --exe options must be set together to give the core"); 57 System.out.println(" file, and associated executable, to operate on. Otherwise the --pid"); 58 System.out.println(" option can be set to operate on a live process."); 59 System.out.println(" The arguments for --exe and --core can use absolute or relative paths."); 60 System.out.println(); 61 System.out.println(" Examples: jhsdb " + mode + " --pid 1234"); 62 System.out.println(" or jhsdb " + mode + " --core ./core.1234 --exe ./myexe"); 63 return false; 64 } 65 66 private static boolean debugdHelp() { 67 // [options] <pid> [server-id] 68 // [options] <executable> <core> [server-id] 69 System.out.println(" --serverid <id> \tA unique identifier for this debug server."); 70 return commonHelp("debugd"); 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("jinfo"); 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 <name>\tThe name 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("jmap"); 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("jstack"); 105 } 106 107 private static boolean jsnapHelp() { 108 System.out.println(" --all \tTo print all performance counters."); 109 return commonHelp("jsnap"); 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")) { 129 return commonHelp("hsdb"); 130 } 131 if (toolName.equals("clhsdb")) { 132 return commonHelp("clhsdb"); 133 } 134 return launcherHelp(); 135 } 136 137 private static void buildAttachArgs(ArrayList<String> newArgs, String pid, 138 String exe, String core, boolean allowEmpty) { 139 if (!allowEmpty && (pid == null) && (exe == null)) { 140 throw new SAGetoptException("You have to set --pid or --exe."); 141 } 142 143 if (pid != null) { // Attach to live process 144 if (exe != null) { 145 throw new SAGetoptException("Unnecessary argument: --exe"); 146 } else if (core != null) { 147 throw new SAGetoptException("Unnecessary argument: --core"); 148 } else if (!pid.matches("^\\d+$")) { 149 throw new SAGetoptException("Invalid pid: " + pid); 150 } 151 152 newArgs.add(pid); 153 } else if (exe != null) { 154 if (exe.length() == 0) { 155 throw new SAGetoptException("You have to set --exe."); 156 } 157 158 newArgs.add(exe); 159 160 if ((core == null) || (core.length() == 0)) { 161 throw new SAGetoptException("You have to set --core."); 162 } 163 164 newArgs.add(core); 165 } 166 } 167 168 private static void runCLHSDB(String[] oldArgs) { 169 SAGetopt sg = new SAGetopt(oldArgs); 170 String[] longOpts = {"exe=", "core=", "pid="}; 171 172 ArrayList<String> newArgs = new ArrayList(); 173 String pid = null; 174 String exe = null; 175 String core = null; 176 String s = null; 177 178 while((s = sg.next(null, longOpts)) != null) { 179 if (s.equals("exe")) { 180 exe = sg.getOptarg(); 181 continue; 182 } 183 if (s.equals("core")) { 184 core = sg.getOptarg(); 185 continue; 186 } 187 if (s.equals("pid")) { 188 pid = sg.getOptarg(); 189 continue; 190 } 191 } 192 193 buildAttachArgs(newArgs, pid, exe, core, true); 194 CLHSDB.main(newArgs.toArray(new String[newArgs.size()])); 195 } 196 197 private static void runHSDB(String[] oldArgs) { 198 SAGetopt sg = new SAGetopt(oldArgs); 199 String[] longOpts = {"exe=", "core=", "pid="}; 200 201 ArrayList<String> newArgs = new ArrayList(); 202 String pid = null; 203 String exe = null; 204 String core = null; 205 String s = null; 206 207 while((s = sg.next(null, longOpts)) != null) { 208 if (s.equals("exe")) { 209 exe = sg.getOptarg(); 210 continue; 211 } 212 if (s.equals("core")) { 213 core = sg.getOptarg(); 214 continue; 215 } 216 if (s.equals("pid")) { 217 pid = sg.getOptarg(); 218 continue; 219 } 220 } 221 222 buildAttachArgs(newArgs, pid, exe, core, true); 223 HSDB.main(newArgs.toArray(new String[newArgs.size()])); 224 } 225 226 private static void runJSTACK(String[] oldArgs) { 227 SAGetopt sg = new SAGetopt(oldArgs); 228 String[] longOpts = {"exe=", "core=", "pid=", 229 "mixed", "locks"}; 230 231 ArrayList<String> newArgs = new ArrayList(); 232 String pid = null; 233 String exe = null; 234 String core = null; 235 String s = null; 236 237 while((s = sg.next(null, longOpts)) != null) { 238 if (s.equals("exe")) { 239 exe = sg.getOptarg(); 240 continue; 241 } 242 if (s.equals("core")) { 243 core = sg.getOptarg(); 244 continue; 245 } 246 if (s.equals("pid")) { 247 pid = sg.getOptarg(); 248 continue; 249 } 250 if (s.equals("mixed")) { 251 newArgs.add("-m"); 252 continue; 253 } 254 if (s.equals("locks")) { 255 newArgs.add("-l"); 256 continue; 257 } 258 } 259 260 buildAttachArgs(newArgs, pid, exe, core, false); 261 JStack jstack = new JStack(false, false); 262 jstack.runWithArgs(newArgs.toArray(new String[newArgs.size()])); 263 } 264 265 private static void runJMAP(String[] oldArgs) { 266 SAGetopt sg = new SAGetopt(oldArgs); 267 String[] longOpts = {"exe=", "core=", "pid=", 268 "heap", "binaryheap", "dumpfile=", "histo", "clstats", "finalizerinfo"}; 269 270 ArrayList<String> newArgs = new ArrayList(); 271 String pid = null; 272 String exe = null; 273 String core = null; 274 String s = null; 275 String dumpfile = null; 276 boolean requestHeapdump = false; 277 278 while((s = sg.next(null, longOpts)) != null) { 279 if (s.equals("exe")) { 280 exe = sg.getOptarg(); 281 continue; 282 } 283 if (s.equals("core")) { 284 core = sg.getOptarg(); 285 continue; 286 } 287 if (s.equals("pid")) { 288 pid = sg.getOptarg(); 289 continue; 290 } 291 if (s.equals("heap")) { 292 newArgs.add("-heap"); 293 continue; 294 } 295 if (s.equals("binaryheap")) { 296 requestHeapdump = true; 297 continue; 298 } 299 if (s.equals("dumpfile")) { 300 dumpfile = sg.getOptarg(); 301 continue; 302 } 303 if (s.equals("histo")) { 304 newArgs.add("-histo"); 305 continue; 306 } 307 if (s.equals("clstats")) { 308 newArgs.add("-clstats"); 309 continue; 310 } 311 if (s.equals("finalizerinfo")) { 312 newArgs.add("-finalizerinfo"); 313 continue; 314 } 315 } 316 317 if (!requestHeapdump && (dumpfile != null)) { 318 throw new IllegalArgumentException("Unexpected argument dumpfile"); 319 } 320 if (requestHeapdump) { 321 if (dumpfile == null) { 322 newArgs.add("-heap:format=b"); 323 } else { 324 newArgs.add("-heap:format=b,file=" + dumpfile); 325 } 326 } 327 328 buildAttachArgs(newArgs, pid, exe, core, false); 329 JMap.main(newArgs.toArray(new String[newArgs.size()])); 330 } 331 332 private static void runJINFO(String[] oldArgs) { 333 SAGetopt sg = new SAGetopt(oldArgs); 334 String[] longOpts = {"exe=", "core=", "pid=", 335 "flags", "sysprops"}; 336 337 ArrayList<String> newArgs = new ArrayList(); 338 String exe = null; 339 String pid = null; 340 String core = null; 341 String s = null; 342 343 while((s = sg.next(null, longOpts)) != null) { 344 if (s.equals("exe")) { 345 exe = sg.getOptarg(); 346 continue; 347 } 348 if (s.equals("core")) { 349 core = sg.getOptarg(); 350 continue; 351 } 352 if (s.equals("pid")) { 353 pid = sg.getOptarg(); 354 continue; 355 } 356 if (s.equals("flags")) { 357 newArgs.add("-flags"); 358 continue; 359 } 360 if (s.equals("sysprops")) { 361 newArgs.add("-sysprops"); 362 continue; 363 } 364 } 365 366 buildAttachArgs(newArgs, pid, exe, core, false); 367 JInfo.main(newArgs.toArray(new String[newArgs.size()])); 368 } 369 370 private static void runJSNAP(String[] oldArgs) { 371 SAGetopt sg = new SAGetopt(oldArgs); 372 String[] longOpts = {"exe=", "core=", "pid=", "all"}; 373 374 ArrayList<String> newArgs = new ArrayList(); 375 String exe = null; 376 String pid = null; 377 String core = null; 378 String s = null; 379 380 while((s = sg.next(null, longOpts)) != null) { 381 if (s.equals("exe")) { 382 exe = sg.getOptarg(); 383 continue; 384 } 385 if (s.equals("core")) { 386 core = sg.getOptarg(); 387 continue; 388 } 389 if (s.equals("pid")) { 390 pid = sg.getOptarg(); 391 continue; 392 } 393 if (s.equals("all")) { 394 newArgs.add("-a"); 395 continue; 396 } 397 } 398 399 buildAttachArgs(newArgs, pid, exe, core, false); 400 JSnap.main(newArgs.toArray(new String[newArgs.size()])); 401 } 402 403 private static void runDEBUGD(String[] oldArgs) { 404 // By default SA agent classes prefer Windows process debugger 405 // to windbg debugger. SA expects special properties to be set 406 // to choose other debuggers. We will set those here before 407 // attaching to SA agent. 408 System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true"); 409 410 SAGetopt sg = new SAGetopt(oldArgs); 411 String[] longOpts = {"exe=", "core=", "pid=", "serverid="}; 412 413 ArrayList<String> newArgs = new ArrayList<>(); 414 String exe = null; 415 String pid = null; 416 String core = null; 417 String s = null; 418 String serverid = null; 419 420 while((s = sg.next(null, longOpts)) != null) { 421 if (s.equals("exe")) { 422 exe = sg.getOptarg(); 423 continue; 424 } 425 if (s.equals("core")) { 426 core = sg.getOptarg(); 427 continue; 428 } 429 if (s.equals("pid")) { 430 pid = sg.getOptarg(); 431 continue; 432 } 433 if (s.equals("serverid")) { 434 serverid = sg.getOptarg(); 435 continue; 436 } 437 } 438 439 buildAttachArgs(newArgs, pid, exe, core, false); 440 if (serverid != null) { 441 newArgs.add(serverid); 442 } 443 444 // delegate to the actual SA debug server. 445 sun.jvm.hotspot.DebugServer.main(newArgs.toArray(new String[newArgs.size()])); 446 } 447 448 public static void main(String[] args) { 449 // Provide a help 450 if (args.length == 0) { 451 launcherHelp(); 452 return; 453 } 454 // No arguments imply help for debugd, jstack, jmap, jinfo but launch clhsdb and hsdb 455 if (args.length == 1 && !args[0].equals("clhsdb") && !args[0].equals("hsdb")) { 456 toolHelp(args[0]); 457 return; 458 } 459 460 for (String arg : args) { 461 if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")) { 462 toolHelp(args[0]); 463 return; 464 } 465 } 466 467 String[] oldArgs = Arrays.copyOfRange(args, 1, args.length); 468 469 try { 470 // Run SA interactive mode 471 if (args[0].equals("clhsdb")) { 472 runCLHSDB(oldArgs); 473 return; 474 } 475 476 if (args[0].equals("hsdb")) { 477 runHSDB(oldArgs); 478 return; 479 } 480 481 // Run SA tmtools mode 482 if (args[0].equals("jstack")) { 483 runJSTACK(oldArgs); 484 return; 485 } 486 487 if (args[0].equals("jmap")) { 488 runJMAP(oldArgs); 489 return; 490 } 491 492 if (args[0].equals("jinfo")) { 493 runJINFO(oldArgs); 494 return; 495 } 496 497 if (args[0].equals("jsnap")) { 498 runJSNAP(oldArgs); 499 return; 500 } 501 502 if (args[0].equals("debugd")) { 503 runDEBUGD(oldArgs); 504 return; 505 } 506 507 throw new SAGetoptException("Unknown tool: " + args[0]); 508 } catch (SAGetoptException e) { 509 System.err.println(e.getMessage()); 510 toolHelp(args[0]); 511 } 512 } 513 }