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