author | vinnie |
Mon, 06 Oct 2014 16:44:57 +0100 | |
changeset 26958 | cb5cbde6e7a4 |
parent 25859 | 3317bb8137f4 |
child 28099 | 44dfaff3cc59 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
7668 | 2 |
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.tools.jstat; |
|
27 |
||
28 |
import java.io.*; |
|
29 |
import java.net.*; |
|
30 |
import java.util.*; |
|
31 |
import java.util.regex.*; |
|
32 |
import sun.jvmstat.monitor.Monitor; |
|
33 |
import sun.jvmstat.monitor.VmIdentifier; |
|
34 |
||
35 |
/** |
|
36 |
* Class for processing command line arguments and providing method |
|
37 |
* level access to arguments. |
|
38 |
* |
|
39 |
* @author Brian Doherty |
|
40 |
* @since 1.5 |
|
41 |
*/ |
|
42 |
public class Arguments { |
|
43 |
||
44 |
private static final boolean debug = Boolean.getBoolean("jstat.debug"); |
|
45 |
private static final boolean showUnsupported = |
|
46 |
Boolean.getBoolean("jstat.showUnsupported"); |
|
47 |
||
48 |
private static final String JVMSTAT_USERDIR = ".jvmstat"; |
|
49 |
private static final String OPTIONS_FILENAME = "jstat_options"; |
|
5778
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
50 |
private static final String UNSUPPORTED_OPTIONS_FILENAME = "jstat_unsupported_options"; |
2 | 51 |
private static final String ALL_NAMES = "\\w*"; |
52 |
||
53 |
private Comparator<Monitor> comparator; |
|
54 |
private int headerRate; |
|
55 |
private boolean help; |
|
56 |
private boolean list; |
|
57 |
private boolean options; |
|
58 |
private boolean constants; |
|
59 |
private boolean constantsOnly; |
|
60 |
private boolean strings; |
|
61 |
private boolean timestamp; |
|
62 |
private boolean snap; |
|
63 |
private boolean verbose; |
|
64 |
private String specialOption; |
|
65 |
private String names; |
|
66 |
||
67 |
private OptionFormat optionFormat; |
|
68 |
||
69 |
private int count = -1; |
|
70 |
private int interval = -1; |
|
71 |
private String vmIdString; |
|
72 |
||
73 |
private VmIdentifier vmId; |
|
74 |
||
75 |
public static void printUsage(PrintStream ps) { |
|
76 |
ps.println("Usage: jstat -help|-options"); |
|
77 |
ps.println(" jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]"); |
|
78 |
ps.println(); |
|
79 |
ps.println("Definitions:"); |
|
80 |
ps.println(" <option> An option reported by the -options option"); |
|
81 |
ps.println(" <vmid> Virtual Machine Identifier. A vmid takes the following form:"); |
|
82 |
ps.println(" <lvmid>[@<hostname>[:<port>]]"); |
|
83 |
ps.println(" Where <lvmid> is the local vm identifier for the target"); |
|
84 |
ps.println(" Java virtual machine, typically a process id; <hostname> is"); |
|
85 |
ps.println(" the name of the host running the target Java virtual machine;"); |
|
86 |
ps.println(" and <port> is the port number for the rmiregistry on the"); |
|
87 |
ps.println(" target host. See the jvmstat documentation for a more complete"); |
|
88 |
ps.println(" description of the Virtual Machine Identifier."); |
|
89 |
ps.println(" <lines> Number of samples between header lines."); |
|
90 |
ps.println(" <interval> Sampling interval. The following forms are allowed:"); |
|
91 |
ps.println(" <n>[\"ms\"|\"s\"]"); |
|
92 |
ps.println(" Where <n> is an integer and the suffix specifies the units as "); |
|
93 |
ps.println(" milliseconds(\"ms\") or seconds(\"s\"). The default units are \"ms\"."); |
|
94 |
ps.println(" <count> Number of samples to take before terminating."); |
|
95 |
ps.println(" -J<flag> Pass <flag> directly to the runtime system."); |
|
96 |
||
97 |
// undocumented options: |
|
98 |
// -list [<vmid>] - list counter names |
|
99 |
// -snap <vmid> - snapshot counter values as name=value pairs |
|
100 |
// -name <pattern> - output counters matching given pattern |
|
101 |
// -a - sort in ascending order (default) |
|
102 |
// -d - sort in descending order |
|
103 |
// -v - verbose output (-snap) |
|
104 |
// -constants - output constants with -name output |
|
105 |
// -strings - output strings with -name output |
|
106 |
} |
|
107 |
||
108 |
private static int toMillis(String s) throws IllegalArgumentException { |
|
109 |
||
110 |
String[] unitStrings = { "ms", "s" }; // ordered from most specific to |
|
111 |
// least specific |
|
112 |
String unitString = null; |
|
113 |
String valueString = s; |
|
114 |
||
115 |
for (int i = 0; i < unitStrings.length; i++) { |
|
116 |
int index = s.indexOf(unitStrings[i]); |
|
117 |
if (index > 0) { |
|
118 |
unitString = s.substring(index); |
|
119 |
valueString = s.substring(0, index); |
|
120 |
break; |
|
121 |
} |
|
122 |
} |
|
123 |
||
124 |
try { |
|
125 |
int value = Integer.parseInt(valueString); |
|
126 |
||
127 |
if (unitString == null || unitString.compareTo("ms") == 0) { |
|
128 |
return value; |
|
129 |
} else if (unitString.compareTo("s") == 0) { |
|
130 |
return value * 1000; |
|
131 |
} else { |
|
132 |
throw new IllegalArgumentException( |
|
133 |
"Unknow time unit: " + unitString); |
|
134 |
} |
|
135 |
} catch (NumberFormatException e) { |
|
136 |
throw new IllegalArgumentException( |
|
137 |
"Could not convert interval: " + s); |
|
138 |
} |
|
139 |
} |
|
140 |
||
141 |
public Arguments(String[] args) throws IllegalArgumentException { |
|
142 |
int argc = 0; |
|
143 |
||
144 |
if (args.length < 1) { |
|
145 |
throw new IllegalArgumentException("invalid argument count"); |
|
146 |
} |
|
147 |
||
148 |
if ((args[0].compareTo("-?") == 0) |
|
149 |
|| (args[0].compareTo("-help") == 0)) { |
|
150 |
help = true; |
|
151 |
return; |
|
152 |
} else if (args[0].compareTo("-options") == 0) { |
|
153 |
options = true; |
|
154 |
return; |
|
155 |
} else if (args[0].compareTo("-list") == 0) { |
|
156 |
list = true; |
|
157 |
if (args.length > 2) { |
|
158 |
throw new IllegalArgumentException("invalid argument count"); |
|
159 |
} |
|
160 |
// list can take one arg - a vmid - fall through for arg processing |
|
161 |
argc++; |
|
162 |
} |
|
163 |
||
164 |
for ( ; (argc < args.length) && (args[argc].startsWith("-")); argc++) { |
|
165 |
String arg = args[argc]; |
|
166 |
||
167 |
if (arg.compareTo("-a") == 0) { |
|
168 |
comparator = new AscendingMonitorComparator(); |
|
169 |
} else if (arg.compareTo("-d") == 0) { |
|
170 |
comparator = new DescendingMonitorComparator(); |
|
171 |
} else if (arg.compareTo("-t") == 0) { |
|
172 |
timestamp = true; |
|
173 |
} else if (arg.compareTo("-v") == 0) { |
|
174 |
verbose = true; |
|
175 |
} else if ((arg.compareTo("-constants") == 0) |
|
176 |
|| (arg.compareTo("-c") == 0)) { |
|
177 |
constants = true; |
|
178 |
} else if ((arg.compareTo("-strings") == 0) |
|
179 |
|| (arg.compareTo("-s") == 0)) { |
|
180 |
strings = true; |
|
181 |
} else if (arg.startsWith("-h")) { |
|
182 |
String value; |
|
183 |
if (arg.compareTo("-h") != 0) { |
|
184 |
value = arg.substring(2); |
|
185 |
} else { |
|
186 |
argc++; |
|
187 |
if (argc >= args.length) { |
|
188 |
throw new IllegalArgumentException( |
|
189 |
"-h requires an integer argument"); |
|
190 |
} |
|
191 |
value = args[argc]; |
|
192 |
} |
|
193 |
try { |
|
194 |
headerRate = Integer.parseInt(value); |
|
195 |
} catch (NumberFormatException e) { |
|
196 |
headerRate = -1; |
|
197 |
} |
|
198 |
if (headerRate < 0) { |
|
199 |
throw new IllegalArgumentException( |
|
200 |
"illegal -h argument: " + value); |
|
201 |
} |
|
202 |
} else if (arg.startsWith("-name")) { |
|
203 |
if (arg.startsWith("-name=")) { |
|
204 |
names = arg.substring(7); |
|
205 |
} else { |
|
206 |
argc++; |
|
207 |
if (argc >= args.length) { |
|
208 |
throw new IllegalArgumentException( |
|
209 |
"option argument expected"); |
|
210 |
} |
|
211 |
names = args[argc]; |
|
212 |
} |
|
213 |
} else { |
|
214 |
/* |
|
215 |
* there are scenarios here: special jstat_options file option |
|
216 |
* or the rare case of a negative lvmid. The negative lvmid |
|
217 |
* can occur in some operating environments (such as Windows |
|
218 |
* 95/98/ME), so we provide for this case here by checking if |
|
219 |
* the argument has any numerical characters. This assumes that |
|
220 |
* there are no special jstat_options that contain numerical |
|
221 |
* characters in their name. |
|
222 |
*/ |
|
223 |
||
224 |
// extract the lvmid part of possible lvmid@host.domain:port |
|
225 |
String lvmidStr = null; |
|
226 |
int at_index = args[argc].indexOf('@'); |
|
227 |
if (at_index < 0) { |
|
228 |
lvmidStr = args[argc]; |
|
229 |
} else { |
|
230 |
lvmidStr = args[argc].substring(0, at_index); |
|
231 |
} |
|
232 |
||
233 |
// try to parse the lvmid part as an integer |
|
234 |
try { |
|
235 |
int vmid = Integer.parseInt(lvmidStr); |
|
236 |
// it parsed, assume a negative lvmid and continue |
|
237 |
break; |
|
238 |
} catch (NumberFormatException nfe) { |
|
239 |
// it didn't parse. check for the -snap or jstat_options |
|
240 |
// file options. |
|
241 |
if ((argc == 0) && (args[argc].compareTo("-snap") == 0)) { |
|
242 |
snap = true; |
|
243 |
} else if (argc == 0) { |
|
244 |
specialOption = args[argc].substring(1); |
|
245 |
} else { |
|
246 |
throw new IllegalArgumentException( |
|
247 |
"illegal argument: " + args[argc]); |
|
248 |
} |
|
249 |
} |
|
250 |
} |
|
251 |
} |
|
252 |
||
253 |
// prevent 'jstat <pid>' from being accepted as a valid argument |
|
254 |
if (!(specialOption != null || list || snap || names != null)) { |
|
255 |
throw new IllegalArgumentException("-<option> required"); |
|
256 |
} |
|
257 |
||
258 |
switch (args.length - argc) { |
|
259 |
case 3: |
|
260 |
if (snap) { |
|
261 |
throw new IllegalArgumentException("invalid argument count"); |
|
262 |
} |
|
263 |
try { |
|
264 |
count = Integer.parseInt(args[args.length-1]); |
|
265 |
} catch (NumberFormatException e) { |
|
266 |
throw new IllegalArgumentException("illegal count value: " |
|
267 |
+ args[args.length-1]); |
|
268 |
} |
|
269 |
interval = toMillis(args[args.length-2]); |
|
270 |
vmIdString = args[args.length-3]; |
|
271 |
break; |
|
272 |
case 2: |
|
273 |
if (snap) { |
|
274 |
throw new IllegalArgumentException("invalid argument count"); |
|
275 |
} |
|
276 |
interval = toMillis(args[args.length-1]); |
|
277 |
vmIdString = args[args.length-2]; |
|
278 |
break; |
|
279 |
case 1: |
|
280 |
vmIdString = args[args.length-1]; |
|
281 |
break; |
|
282 |
case 0: |
|
283 |
if (!list) { |
|
284 |
throw new IllegalArgumentException("invalid argument count"); |
|
285 |
} |
|
286 |
break; |
|
287 |
default: |
|
288 |
throw new IllegalArgumentException("invalid argument count"); |
|
289 |
} |
|
290 |
||
291 |
// set count and interval to their default values if not set above. |
|
292 |
if (count == -1 && interval == -1) { |
|
293 |
// default is for a single sample |
|
294 |
count = 1; |
|
295 |
interval = 0; |
|
296 |
} |
|
297 |
||
298 |
// validate arguments |
|
299 |
if (comparator == null) { |
|
300 |
comparator = new AscendingMonitorComparator(); |
|
301 |
} |
|
302 |
||
303 |
// allow ',' characters to separate names, convert to '|' chars |
|
304 |
names = (names == null) ? ALL_NAMES : names.replace(',', '|'); |
|
305 |
||
306 |
// verify that the given pattern parses without errors |
|
307 |
try { |
|
308 |
Pattern pattern = Pattern.compile(names); |
|
309 |
} catch (PatternSyntaxException e) { |
|
310 |
throw new IllegalArgumentException("Bad name pattern: " |
|
311 |
+ e.getMessage()); |
|
312 |
} |
|
313 |
||
314 |
// verify that the special option is valid and get it's formatter |
|
315 |
if (specialOption != null) { |
|
316 |
OptionFinder finder = new OptionFinder(optionsSources()); |
|
317 |
optionFormat = finder.getOptionFormat(specialOption, timestamp); |
|
318 |
if (optionFormat == null) { |
|
319 |
throw new IllegalArgumentException("Unknown option: -" |
|
320 |
+ specialOption); |
|
321 |
} |
|
322 |
} |
|
323 |
||
324 |
// verify that the vm identifier is valied |
|
325 |
try { |
|
326 |
vmId = new VmIdentifier(vmIdString); |
|
327 |
} catch (URISyntaxException e) { |
|
328 |
IllegalArgumentException iae = new IllegalArgumentException( |
|
329 |
"Malformed VM Identifier: " + vmIdString); |
|
330 |
iae.initCause(e); |
|
331 |
throw iae; |
|
332 |
} |
|
333 |
} |
|
334 |
||
335 |
public Comparator<Monitor> comparator() { |
|
336 |
return comparator; |
|
337 |
} |
|
338 |
||
339 |
public boolean isHelp() { |
|
340 |
return help; |
|
341 |
} |
|
342 |
||
343 |
public boolean isList() { |
|
344 |
return list; |
|
345 |
} |
|
346 |
||
347 |
public boolean isSnap() { |
|
348 |
return snap; |
|
349 |
} |
|
350 |
||
351 |
public boolean isOptions() { |
|
352 |
return options; |
|
353 |
} |
|
354 |
||
355 |
public boolean isVerbose() { |
|
356 |
return verbose; |
|
357 |
} |
|
358 |
||
359 |
public boolean printConstants() { |
|
360 |
return constants; |
|
361 |
} |
|
362 |
||
363 |
public boolean isConstantsOnly() { |
|
364 |
return constantsOnly; |
|
365 |
} |
|
366 |
||
367 |
public boolean printStrings() { |
|
368 |
return strings; |
|
369 |
} |
|
370 |
||
371 |
public boolean showUnsupported() { |
|
372 |
return showUnsupported; |
|
373 |
} |
|
374 |
||
375 |
public int headerRate() { |
|
376 |
return headerRate; |
|
377 |
} |
|
378 |
||
379 |
public String counterNames() { |
|
380 |
return names; |
|
381 |
} |
|
382 |
||
383 |
public VmIdentifier vmId() { |
|
384 |
return vmId; |
|
385 |
} |
|
386 |
||
387 |
public String vmIdString() { |
|
388 |
return vmIdString; |
|
389 |
} |
|
390 |
||
391 |
public int sampleInterval() { |
|
392 |
return interval; |
|
393 |
} |
|
394 |
||
395 |
public int sampleCount() { |
|
396 |
return count; |
|
397 |
} |
|
398 |
||
399 |
public boolean isTimestamp() { |
|
400 |
return timestamp; |
|
401 |
} |
|
402 |
||
403 |
public boolean isSpecialOption() { |
|
404 |
return specialOption != null; |
|
405 |
} |
|
406 |
||
407 |
public String specialOption() { |
|
408 |
return specialOption; |
|
409 |
} |
|
410 |
||
411 |
public OptionFormat optionFormat() { |
|
412 |
return optionFormat; |
|
413 |
} |
|
414 |
||
5778
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
415 |
public List<URL> optionsSources() { |
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
416 |
List<URL> sources = new ArrayList<URL>(); |
2 | 417 |
int i = 0; |
418 |
||
419 |
String filename = OPTIONS_FILENAME; |
|
420 |
||
421 |
try { |
|
422 |
String userHome = System.getProperty("user.home"); |
|
423 |
String userDir = userHome + "/" + JVMSTAT_USERDIR; |
|
424 |
File home = new File(userDir + "/" + filename); |
|
5778
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
425 |
sources.add(home.toURI().toURL()); |
2 | 426 |
} catch (Exception e) { |
427 |
if (debug) { |
|
428 |
System.err.println(e.getMessage()); |
|
429 |
e.printStackTrace(); |
|
430 |
} |
|
431 |
throw new IllegalArgumentException("Internal Error: Bad URL: " |
|
432 |
+ e.getMessage()); |
|
433 |
} |
|
5778
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
434 |
URL u = this.getClass().getResource("resources/" + filename); |
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
435 |
assert u != null; |
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
436 |
sources.add(u); |
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
437 |
|
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
438 |
if (showUnsupported) { |
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
439 |
u = this.getClass().getResource("resources/" + UNSUPPORTED_OPTIONS_FILENAME); |
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
440 |
assert u != null; |
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
441 |
sources.add(u); |
ca3811dc046d
6959965: jstat: Add new -classload option to print class loading statistics
mchung
parents:
5506
diff
changeset
|
442 |
} |
2 | 443 |
return sources; |
444 |
} |
|
445 |
} |