44 System.out.println(" jsnap --help\tto get more information"); |
49 System.out.println(" jsnap --help\tto get more information"); |
45 return false; |
50 return false; |
46 } |
51 } |
47 |
52 |
48 private static boolean commonHelp(String mode) { |
53 private static boolean commonHelp(String mode) { |
|
54 return commonHelp(mode, false); |
|
55 } |
|
56 |
|
57 private static boolean commonHelpWithConnect(String mode) { |
|
58 return commonHelp(mode, true); |
|
59 } |
|
60 |
|
61 private static boolean commonHelp(String mode, boolean canConnectToRemote) { |
49 // --pid <pid> |
62 // --pid <pid> |
50 // --exe <exe> |
63 // --exe <exe> |
51 // --core <core> |
64 // --core <core> |
52 System.out.println(" --pid <pid> \tTo attach to and operate on the given live process."); |
65 // --connect [<id>@]<host> |
53 System.out.println(" --core <corefile>\tTo operate on the given core file."); |
66 System.out.println(" --pid <pid> To attach to and operate on the given live process."); |
|
67 System.out.println(" --core <corefile> To operate on the given core file."); |
54 System.out.println(" --exe <executable for corefile>"); |
68 System.out.println(" --exe <executable for corefile>"); |
|
69 if (canConnectToRemote) { |
|
70 System.out.println(" --connect [<id>@]<host> To connect to a remote debug server (debugd)."); |
|
71 } |
55 System.out.println(); |
72 System.out.println(); |
56 System.out.println(" The --core and --exe options must be set together to give the core"); |
73 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"); |
74 System.out.println(" file, and associated executable, to operate on. They can use"); |
58 System.out.println(" option can be set to operate on a live process."); |
75 System.out.println(" absolute or relative paths."); |
59 System.out.println(" The arguments for --exe and --core can use absolute or relative paths."); |
76 System.out.println(" The --pid option can be set to operate on a live process."); |
|
77 if (canConnectToRemote) { |
|
78 System.out.println(" The --connect option can be set to connect to a debug server (debugd)."); |
|
79 System.out.println(" --core, --pid, and --connect are mutually exclusive."); |
|
80 } else { |
|
81 System.out.println(" --core and --pid are mutually exclusive."); |
|
82 } |
60 System.out.println(); |
83 System.out.println(); |
61 System.out.println(" Examples: jhsdb " + mode + " --pid 1234"); |
84 System.out.println(" Examples: jhsdb " + mode + " --pid 1234"); |
62 System.out.println(" or jhsdb " + mode + " --core ./core.1234 --exe ./myexe"); |
85 System.out.println(" or jhsdb " + mode + " --core ./core.1234 --exe ./myexe"); |
|
86 if (canConnectToRemote) { |
|
87 System.out.println(" or jhsdb " + mode + " --connect debugserver"); |
|
88 System.out.println(" or jhsdb " + mode + " --connect id@debugserver"); |
|
89 } |
63 return false; |
90 return false; |
64 } |
91 } |
65 |
92 |
66 private static boolean debugdHelp() { |
93 private static boolean debugdHelp() { |
67 // [options] <pid> [server-id] |
94 // [options] <pid> [server-id] |
68 // [options] <executable> <core> [server-id] |
95 // [options] <executable> <core> [server-id] |
69 System.out.println(" --serverid <id> \tA unique identifier for this debug server."); |
96 System.out.println(" --serverid <id> A unique identifier for this debug server."); |
70 return commonHelp("debugd"); |
97 return commonHelp("debugd"); |
71 } |
98 } |
72 |
99 |
73 private static boolean jinfoHelp() { |
100 private static boolean jinfoHelp() { |
74 // --flags -> -flags |
101 // --flags -> -flags |
75 // --sysprops -> -sysprops |
102 // --sysprops -> -sysprops |
76 System.out.println(" --flags \tTo print VM flags."); |
103 System.out.println(" --flags To print VM flags."); |
77 System.out.println(" --sysprops \tTo print Java System properties."); |
104 System.out.println(" --sysprops To print Java System properties."); |
78 System.out.println(" <no option> \tTo print both of the above."); |
105 System.out.println(" <no option> To print both of the above."); |
79 return commonHelp("jinfo"); |
106 return commonHelpWithConnect("jinfo"); |
80 } |
107 } |
81 |
108 |
82 private static boolean jmapHelp() { |
109 private static boolean jmapHelp() { |
83 // --heap -> -heap |
110 // --heap -> -heap |
84 // --binaryheap -> -heap:format=b |
111 // --binaryheap -> -heap:format=b |
85 // --histo -> -histo |
112 // --histo -> -histo |
86 // --clstats -> -clstats |
113 // --clstats -> -clstats |
87 // --finalizerinfo -> -finalizerinfo |
114 // --finalizerinfo -> -finalizerinfo |
88 |
115 |
89 System.out.println(" <no option> \tTo print same info as Solaris pmap."); |
116 System.out.println(" <no option> To print same info as Solaris pmap."); |
90 System.out.println(" --heap \tTo print java heap summary."); |
117 System.out.println(" --heap To print java heap summary."); |
91 System.out.println(" --binaryheap \tTo dump java heap in hprof binary format."); |
118 System.out.println(" --binaryheap To dump java heap in hprof binary format."); |
92 System.out.println(" --dumpfile <name>\tThe name of the dump file."); |
119 System.out.println(" --dumpfile <name> The name of the dump file."); |
93 System.out.println(" --histo \tTo print histogram of java object heap."); |
120 System.out.println(" --histo To print histogram of java object heap."); |
94 System.out.println(" --clstats \tTo print class loader statistics."); |
121 System.out.println(" --clstats To print class loader statistics."); |
95 System.out.println(" --finalizerinfo \tTo print information on objects awaiting finalization."); |
122 System.out.println(" --finalizerinfo To print information on objects awaiting finalization."); |
96 return commonHelp("jmap"); |
123 return commonHelpWithConnect("jmap"); |
97 } |
124 } |
98 |
125 |
99 private static boolean jstackHelp() { |
126 private static boolean jstackHelp() { |
100 // --locks -> -l |
127 // --locks -> -l |
101 // --mixed -> -m |
128 // --mixed -> -m |
102 System.out.println(" --locks \tTo print java.util.concurrent locks."); |
129 System.out.println(" --locks To print java.util.concurrent locks."); |
103 System.out.println(" --mixed \tTo print both Java and native frames (mixed mode)."); |
130 System.out.println(" --mixed To print both Java and native frames (mixed mode)."); |
104 return commonHelp("jstack"); |
131 return commonHelpWithConnect("jstack"); |
105 } |
132 } |
106 |
133 |
107 private static boolean jsnapHelp() { |
134 private static boolean jsnapHelp() { |
108 System.out.println(" --all \tTo print all performance counters."); |
135 System.out.println(" --all To print all performance counters."); |
109 return commonHelp("jsnap"); |
136 return commonHelpWithConnect("jsnap"); |
110 } |
137 } |
111 |
138 |
112 private static boolean toolHelp(String toolName) { |
139 private static boolean toolHelp(String toolName) { |
113 if (toolName.equals("jstack")) { |
140 switch (toolName) { |
114 return jstackHelp(); |
141 case "jstack": |
115 } |
142 return jstackHelp(); |
116 if (toolName.equals("jinfo")) { |
143 case "jinfo": |
117 return jinfoHelp(); |
144 return jinfoHelp(); |
118 } |
145 case "jmap": |
119 if (toolName.equals("jmap")) { |
146 return jmapHelp(); |
120 return jmapHelp(); |
147 case "jsnap": |
121 } |
148 return jsnapHelp(); |
122 if (toolName.equals("jsnap")) { |
149 case "debugd": |
123 return jsnapHelp(); |
150 return debugdHelp(); |
124 } |
151 case "hsdb": |
125 if (toolName.equals("debugd")) { |
152 case "clhsdb": |
126 return debugdHelp(); |
153 return commonHelp(toolName); |
127 } |
154 default: |
128 if (toolName.equals("hsdb")) { |
155 return launcherHelp(); |
129 return commonHelp("hsdb"); |
156 } |
130 } |
157 } |
131 if (toolName.equals("clhsdb")) { |
158 |
132 return commonHelp("clhsdb"); |
159 private static final String NO_REMOTE = null; |
133 } |
160 |
134 return launcherHelp(); |
161 private static String[] buildAttachArgs(Map<String, String> newArgMap, |
135 } |
162 boolean allowEmpty) { |
136 |
163 String pid = newArgMap.remove("pid"); |
137 private static void buildAttachArgs(ArrayList<String> newArgs, String pid, |
164 String exe = newArgMap.remove("exe"); |
138 String exe, String core, boolean allowEmpty) { |
165 String core = newArgMap.remove("core"); |
139 if (!allowEmpty && (pid == null) && (exe == null)) { |
166 String connect = newArgMap.remove("connect"); |
140 throw new SAGetoptException("You have to set --pid or --exe."); |
167 if (!allowEmpty && (pid == null) && (exe == null) && (connect == NO_REMOTE)) { |
|
168 throw new SAGetoptException("You have to set --pid or --exe or --connect."); |
|
169 } |
|
170 |
|
171 List<String> newArgs = new ArrayList<>(); |
|
172 for (var entry : newArgMap.entrySet()) { |
|
173 newArgs.add(entry.getKey()); |
|
174 if (entry.getValue() != null) { |
|
175 newArgs.add(entry.getValue()); |
|
176 } |
141 } |
177 } |
142 |
178 |
143 if (pid != null) { // Attach to live process |
179 if (pid != null) { // Attach to live process |
144 if (exe != null) { |
180 if (exe != null) { |
145 throw new SAGetoptException("Unnecessary argument: --exe"); |
181 throw new SAGetoptException("Unnecessary argument: --exe"); |
146 } else if (core != null) { |
182 } else if (core != null) { |
147 throw new SAGetoptException("Unnecessary argument: --core"); |
183 throw new SAGetoptException("Unnecessary argument: --core"); |
|
184 } else if (connect != NO_REMOTE) { |
|
185 throw new SAGetoptException("Unnecessary argument: --connect"); |
148 } else if (!pid.matches("^\\d+$")) { |
186 } else if (!pid.matches("^\\d+$")) { |
149 throw new SAGetoptException("Invalid pid: " + pid); |
187 throw new SAGetoptException("Invalid pid: " + pid); |
150 } |
188 } |
151 |
189 |
152 newArgs.add(pid); |
190 newArgs.add(pid); |
153 } else if (exe != null) { |
191 } else if (exe != null) { |
154 if (exe.length() == 0) { |
192 if (connect != NO_REMOTE) { |
|
193 throw new SAGetoptException("Unnecessary argument: --connect"); |
|
194 } else if (exe.length() == 0) { |
155 throw new SAGetoptException("You have to set --exe."); |
195 throw new SAGetoptException("You have to set --exe."); |
156 } |
196 } |
157 |
197 |
158 newArgs.add(exe); |
198 newArgs.add(exe); |
159 |
199 |
160 if ((core == null) || (core.length() == 0)) { |
200 if ((core == null) || (core.length() == 0)) { |
161 throw new SAGetoptException("You have to set --core."); |
201 throw new SAGetoptException("You have to set --core."); |
162 } |
202 } |
163 |
203 |
164 newArgs.add(core); |
204 newArgs.add(core); |
165 } |
205 } else if (connect != NO_REMOTE) { |
|
206 newArgs.add(connect); |
|
207 } |
|
208 |
|
209 return newArgs.toArray(new String[0]); |
|
210 } |
|
211 |
|
212 /** |
|
213 * This method converts jhsdb-style options (oldArgs) to old fashioned |
|
214 * style. SALauncher delegates the work to the entry point of each tool. |
|
215 * Thus we need to convert the arguments. |
|
216 * For example, `jhsdb jstack --mixed` needs to be converted to `jstack -m`. |
|
217 * |
|
218 * longOptsMap holds the rule how this method should convert the args. |
|
219 * The key is the name of jhsdb style, the value is the name of |
|
220 * old fashioned style. If you want to convert mixed option in jstack, |
|
221 * you need to set "mixed" to the key, and to set "-m" to the value |
|
222 * in longOptsMap. If the option have the value, you need to add "=" to |
|
223 * the key like "exe=". |
|
224 * |
|
225 * You also can set the options which cannot be mapped to old fashioned |
|
226 * arguments. For example, `jhsdb jmap --binaryheap` cannot be mapped to |
|
227 * `jmap` option directly. But you set it to longOptsMap, then you can know |
|
228 * the user sets "binaryheap" option, and SALauncher should set |
|
229 * "-heap:format:b" to jmap option. |
|
230 * |
|
231 * This method returns the map of the old fashioned key/val pairs. |
|
232 * It can be used to build args in string array at buildAttachArgs(). |
|
233 */ |
|
234 private static Map<String, String> parseOptions(String[] oldArgs, |
|
235 Map<String, String> longOptsMap) { |
|
236 SAGetopt sg = new SAGetopt(oldArgs); |
|
237 String[] longOpts = longOptsMap.keySet().toArray(new String[0]); |
|
238 Map<String, String> newArgMap = new HashMap<>(); |
|
239 |
|
240 /* |
|
241 * Parse each jhsdb-style option via SAGetopt. |
|
242 * SAGetopt parses and validates the argument. If the user passes invalid |
|
243 * option, SAGetoptException will be occurred at SAGetopt::next. |
|
244 * Thus there is no need to validate it here. |
|
245 * |
|
246 * We can get option value via SAGetopt::get. If jhsdb-style option has |
|
247 * '=' at the tail, we put old fashioned option with it to newArgMap. |
|
248 */ |
|
249 String s; |
|
250 while ((s = sg.next(null, longOpts)) != null) { |
|
251 var val = longOptsMap.get(s); |
|
252 if (val != null) { |
|
253 newArgMap.put(val, null); |
|
254 } else { |
|
255 val = longOptsMap.get(s + "="); |
|
256 if (val != null) { |
|
257 newArgMap.put(val, sg.getOptarg()); |
|
258 } |
|
259 } |
|
260 } |
|
261 |
|
262 return newArgMap; |
166 } |
263 } |
167 |
264 |
168 private static void runCLHSDB(String[] oldArgs) { |
265 private static void runCLHSDB(String[] oldArgs) { |
169 SAGetopt sg = new SAGetopt(oldArgs); |
266 Map<String, String> longOptsMap = Map.of("exe=", "exe", |
170 String[] longOpts = {"exe=", "core=", "pid="}; |
267 "core=", "core", |
171 |
268 "pid=", "pid"); |
172 ArrayList<String> newArgs = new ArrayList(); |
269 Map<String, String> newArgMap = parseOptions(oldArgs, longOptsMap); |
173 String pid = null; |
270 CLHSDB.main(buildAttachArgs(newArgMap, true)); |
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 } |
271 } |
196 |
272 |
197 private static void runHSDB(String[] oldArgs) { |
273 private static void runHSDB(String[] oldArgs) { |
198 SAGetopt sg = new SAGetopt(oldArgs); |
274 Map<String, String> longOptsMap = Map.of("exe=", "exe", |
199 String[] longOpts = {"exe=", "core=", "pid="}; |
275 "core=", "core", |
200 |
276 "pid=", "pid"); |
201 ArrayList<String> newArgs = new ArrayList(); |
277 Map<String, String> newArgMap = parseOptions(oldArgs, longOptsMap); |
202 String pid = null; |
278 HSDB.main(buildAttachArgs(newArgMap, true)); |
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 } |
279 } |
225 |
280 |
226 private static void runJSTACK(String[] oldArgs) { |
281 private static void runJSTACK(String[] oldArgs) { |
227 SAGetopt sg = new SAGetopt(oldArgs); |
282 Map<String, String> longOptsMap = Map.of("exe=", "exe", |
228 String[] longOpts = {"exe=", "core=", "pid=", |
283 "core=", "core", |
229 "mixed", "locks"}; |
284 "pid=", "pid", |
230 |
285 "connect=", "connect", |
231 ArrayList<String> newArgs = new ArrayList(); |
286 "mixed", "-m", |
232 String pid = null; |
287 "locks", "-l"); |
233 String exe = null; |
288 Map<String, String> newArgMap = parseOptions(oldArgs, longOptsMap); |
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); |
289 JStack jstack = new JStack(false, false); |
262 jstack.runWithArgs(newArgs.toArray(new String[newArgs.size()])); |
290 jstack.runWithArgs(buildAttachArgs(newArgMap, false)); |
263 } |
291 } |
264 |
292 |
265 private static void runJMAP(String[] oldArgs) { |
293 private static void runJMAP(String[] oldArgs) { |
266 SAGetopt sg = new SAGetopt(oldArgs); |
294 Map<String, String> longOptsMap = Map.of("exe=", "exe", |
267 String[] longOpts = {"exe=", "core=", "pid=", |
295 "core=", "core", |
268 "heap", "binaryheap", "dumpfile=", "histo", "clstats", "finalizerinfo"}; |
296 "pid=", "pid", |
269 |
297 "connect=", "connect", |
270 ArrayList<String> newArgs = new ArrayList(); |
298 "heap", "-heap", |
271 String pid = null; |
299 "binaryheap", "binaryheap", |
272 String exe = null; |
300 "dumpfile=", "dumpfile", |
273 String core = null; |
301 "histo", "-histo", |
274 String s = null; |
302 "clstats", "-clstats", |
275 String dumpfile = null; |
303 "finalizerinfo", "-finalizerinfo"); |
276 boolean requestHeapdump = false; |
304 Map<String, String> newArgMap = parseOptions(oldArgs, longOptsMap); |
277 |
305 |
278 while((s = sg.next(null, longOpts)) != null) { |
306 boolean requestHeapdump = newArgMap.containsKey("binaryheap"); |
279 if (s.equals("exe")) { |
307 String dumpfile = newArgMap.get("dumpfile"); |
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)) { |
308 if (!requestHeapdump && (dumpfile != null)) { |
318 throw new IllegalArgumentException("Unexpected argument dumpfile"); |
309 throw new IllegalArgumentException("Unexpected argument: dumpfile"); |
319 } |
310 } |
320 if (requestHeapdump) { |
311 if (requestHeapdump) { |
321 if (dumpfile == null) { |
312 if (dumpfile == null) { |
322 newArgs.add("-heap:format=b"); |
313 newArgMap.put("-heap:format=b", null); |
323 } else { |
314 } else { |
324 newArgs.add("-heap:format=b,file=" + dumpfile); |
315 newArgMap.put("-heap:format=b,file=" + dumpfile, null); |
325 } |
316 } |
326 } |
317 } |
327 |
318 |
328 buildAttachArgs(newArgs, pid, exe, core, false); |
319 newArgMap.remove("binaryheap"); |
329 JMap.main(newArgs.toArray(new String[newArgs.size()])); |
320 newArgMap.remove("dumpfile"); |
|
321 JMap.main(buildAttachArgs(newArgMap, false)); |
330 } |
322 } |
331 |
323 |
332 private static void runJINFO(String[] oldArgs) { |
324 private static void runJINFO(String[] oldArgs) { |
333 SAGetopt sg = new SAGetopt(oldArgs); |
325 Map<String, String> longOptsMap = Map.of("exe=", "exe", |
334 String[] longOpts = {"exe=", "core=", "pid=", |
326 "core=", "core", |
335 "flags", "sysprops"}; |
327 "pid=", "pid", |
336 |
328 "connect=", "connect", |
337 ArrayList<String> newArgs = new ArrayList(); |
329 "flags", "-flags", |
338 String exe = null; |
330 "sysprops", "-sysprops"); |
339 String pid = null; |
331 Map<String, String> newArgMap = parseOptions(oldArgs, longOptsMap); |
340 String core = null; |
332 JInfo.main(buildAttachArgs(newArgMap, false)); |
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 } |
333 } |
369 |
334 |
370 private static void runJSNAP(String[] oldArgs) { |
335 private static void runJSNAP(String[] oldArgs) { |
371 SAGetopt sg = new SAGetopt(oldArgs); |
336 Map<String, String> longOptsMap = Map.of("exe=", "exe", |
372 String[] longOpts = {"exe=", "core=", "pid=", "all"}; |
337 "core=", "core", |
373 |
338 "pid=", "pid", |
374 ArrayList<String> newArgs = new ArrayList(); |
339 "connect=", "connect", |
375 String exe = null; |
340 "all", "-a"); |
376 String pid = null; |
341 Map<String, String> newArgMap = parseOptions(oldArgs, longOptsMap); |
377 String core = null; |
342 JSnap.main(buildAttachArgs(newArgMap, false)); |
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 } |
343 } |
402 |
344 |
403 private static void runDEBUGD(String[] oldArgs) { |
345 private static void runDEBUGD(String[] oldArgs) { |
404 // By default SA agent classes prefer Windows process debugger |
346 // By default SA agent classes prefer Windows process debugger |
405 // to windbg debugger. SA expects special properties to be set |
347 // to windbg debugger. SA expects special properties to be set |
406 // to choose other debuggers. We will set those here before |
348 // to choose other debuggers. We will set those here before |
407 // attaching to SA agent. |
349 // attaching to SA agent. |
408 System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true"); |
350 System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true"); |
409 |
351 |
410 SAGetopt sg = new SAGetopt(oldArgs); |
352 Map<String, String> longOptsMap = Map.of("exe=", "exe", |
411 String[] longOpts = {"exe=", "core=", "pid=", "serverid="}; |
353 "core=", "core", |
412 |
354 "pid=", "pid", |
413 ArrayList<String> newArgs = new ArrayList<>(); |
355 "serverid=", "serverid"); |
414 String exe = null; |
356 Map<String, String> newArgMap = parseOptions(oldArgs, longOptsMap); |
415 String pid = null; |
357 var serverid = newArgMap.remove("serverid"); |
416 String core = null; |
358 List<String> newArgArray = new ArrayList<>(); |
417 String s = null; |
359 newArgArray.addAll(Arrays.asList(buildAttachArgs(newArgMap, false))); |
418 String serverid = null; |
360 |
419 |
361 // `serverid` must be located at the tail. |
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) { |
362 if (serverid != null) { |
441 newArgs.add(serverid); |
363 newArgArray.add(serverid); |
442 } |
364 } |
443 |
365 |
444 // delegate to the actual SA debug server. |
366 // delegate to the actual SA debug server. |
445 sun.jvm.hotspot.DebugServer.main(newArgs.toArray(new String[newArgs.size()])); |
367 DebugServer.main(newArgArray.toArray(new String[0])); |
446 } |
368 } |
|
369 |
|
370 // Key: tool name, Value: launcher method |
|
371 private static Map<String, Consumer<String[]>> toolMap = |
|
372 Map.of("clhsdb", SALauncher::runCLHSDB, |
|
373 "hsdb", SALauncher::runHSDB, |
|
374 "jstack", SALauncher::runJSTACK, |
|
375 "jmap", SALauncher::runJMAP, |
|
376 "jinfo", SALauncher::runJINFO, |
|
377 "jsnap", SALauncher::runJSNAP, |
|
378 "debugd", SALauncher::runDEBUGD); |
447 |
379 |
448 public static void main(String[] args) { |
380 public static void main(String[] args) { |
449 // Provide a help |
381 // Provide a help |
450 if (args.length == 0) { |
382 if (args.length == 0) { |
451 launcherHelp(); |
383 launcherHelp(); |