Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/jmap/JMap.java
38918 views
1
/*
2
* Copyright (c) 2005, 2013, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
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
*
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.
24
*/
25
26
package sun.tools.jmap;
27
28
import java.lang.reflect.Method;
29
import java.io.File;
30
import java.io.IOException;
31
import java.io.InputStream;
32
33
import com.sun.tools.attach.VirtualMachine;
34
import com.sun.tools.attach.AttachNotSupportedException;
35
import sun.tools.attach.HotSpotVirtualMachine;
36
37
/*
38
* This class is the main class for the JMap utility. It parses its arguments
39
* and decides if the command should be satisfied using the VM attach mechanism
40
* or an SA tool. At this time the only option that uses the VM attach mechanism
41
* is the -dump option to get a heap dump of a running application. All other
42
* options are mapped to SA tools.
43
*/
44
public class JMap {
45
46
// Options handled by the attach mechanism
47
private static String HISTO_OPTION = "-histo";
48
private static String LIVE_HISTO_OPTION = "-histo:live";
49
private static String DUMP_OPTION_PREFIX = "-dump:";
50
51
// These options imply the use of a SA tool
52
private static String SA_TOOL_OPTIONS =
53
"-heap|-heap:format=b|-clstats|-finalizerinfo";
54
55
// The -F (force) option is currently not passed through to SA
56
private static String FORCE_SA_OPTION = "-F";
57
58
// Default option (if nothing provided)
59
private static String DEFAULT_OPTION = "-pmap";
60
61
public static void main(String[] args) throws Exception {
62
if (args.length == 0) {
63
usage(1); // no arguments
64
}
65
66
// used to indicate if we should use SA
67
boolean useSA = false;
68
69
// the chosen option (-heap, -dump:*, ... )
70
String option = null;
71
72
// First iterate over the options (arguments starting with -). There should be
73
// one (but maybe two if -F is also used).
74
int optionCount = 0;
75
while (optionCount < args.length) {
76
String arg = args[optionCount];
77
if (!arg.startsWith("-")) {
78
break;
79
}
80
if (arg.equals("-help") || arg.equals("-h")) {
81
usage(0);
82
} else if (arg.equals(FORCE_SA_OPTION)) {
83
useSA = true;
84
} else {
85
if (option != null) {
86
usage(1); // option already specified
87
}
88
option = arg;
89
}
90
optionCount++;
91
}
92
93
// if no option provided then use default.
94
if (option == null) {
95
option = DEFAULT_OPTION;
96
}
97
if (option.matches(SA_TOOL_OPTIONS)) {
98
useSA = true;
99
}
100
101
// Next we check the parameter count. For the SA tools there are
102
// one or two parameters. For the built-in -dump option there is
103
// only one parameter (the process-id)
104
int paramCount = args.length - optionCount;
105
if (paramCount == 0 || paramCount > 2) {
106
usage(1);
107
}
108
109
if (optionCount == 0 || paramCount != 1) {
110
useSA = true;
111
} else {
112
// the parameter for the -dump option is a process-id.
113
// If it doesn't parse to a number then it must be SA
114
// debug server
115
if (!args[optionCount].matches("[0-9]+")) {
116
useSA = true;
117
}
118
}
119
120
121
// at this point we know if we are executing an SA tool or a built-in
122
// option.
123
124
if (useSA) {
125
// parameters (<pid> or <exe> <core>)
126
String params[] = new String[paramCount];
127
for (int i=optionCount; i<args.length; i++ ){
128
params[i-optionCount] = args[i];
129
}
130
runTool(option, params);
131
132
} else {
133
String pid = args[1];
134
// Here we handle the built-in options
135
// As more options are added we should create an abstract tool class and
136
// have a table to map the options
137
if (option.equals(HISTO_OPTION)) {
138
histo(pid, false);
139
} else if (option.equals(LIVE_HISTO_OPTION)) {
140
histo(pid, true);
141
} else if (option.startsWith(DUMP_OPTION_PREFIX)) {
142
dump(pid, option);
143
} else {
144
usage(1);
145
}
146
}
147
}
148
149
// Invoke SA tool with the given arguments
150
private static void runTool(String option, String args[]) throws Exception {
151
String[][] tools = {
152
{ "-pmap", "sun.jvm.hotspot.tools.PMap" },
153
{ "-heap", "sun.jvm.hotspot.tools.HeapSummary" },
154
{ "-heap:format=b", "sun.jvm.hotspot.tools.HeapDumper" },
155
{ "-histo", "sun.jvm.hotspot.tools.ObjectHistogram" },
156
{ "-clstats", "sun.jvm.hotspot.tools.ClassLoaderStats" },
157
{ "-finalizerinfo", "sun.jvm.hotspot.tools.FinalizerInfo" },
158
};
159
160
String tool = null;
161
162
// -dump option needs to be handled in a special way
163
if (option.startsWith(DUMP_OPTION_PREFIX)) {
164
// first check that the option can be parsed
165
String fn = parseDumpOptions(option);
166
if (fn == null) {
167
usage(1);
168
}
169
170
// tool for heap dumping
171
tool = "sun.jvm.hotspot.tools.HeapDumper";
172
173
// HeapDumper -f <file>
174
args = prepend(fn, args);
175
args = prepend("-f", args);
176
} else {
177
int i=0;
178
while (i < tools.length) {
179
if (option.equals(tools[i][0])) {
180
tool = tools[i][1];
181
break;
182
}
183
i++;
184
}
185
}
186
if (tool == null) {
187
usage(1); // no mapping to tool
188
}
189
190
// Tool not available on this platform.
191
Class<?> c = loadClass(tool);
192
if (c == null) {
193
usage(1);
194
}
195
196
// invoke the main method with the arguments
197
Class[] argTypes = { String[].class } ;
198
Method m = c.getDeclaredMethod("main", argTypes);
199
200
Object[] invokeArgs = { args };
201
m.invoke(null, invokeArgs);
202
}
203
204
// loads the given class using the system class loader
205
private static Class<?> loadClass(String name) {
206
//
207
// We specify the system clas loader so as to cater for development
208
// environments where this class is on the boot class path but sa-jdi.jar
209
// is on the system class path. Once the JDK is deployed then both
210
// tools.jar and sa-jdi.jar are on the system class path.
211
//
212
try {
213
return Class.forName(name, true,
214
ClassLoader.getSystemClassLoader());
215
} catch (Exception x) { }
216
return null;
217
}
218
219
private static final String LIVE_OBJECTS_OPTION = "-live";
220
private static final String ALL_OBJECTS_OPTION = "-all";
221
private static void histo(String pid, boolean live) throws IOException {
222
VirtualMachine vm = attach(pid);
223
InputStream in = ((HotSpotVirtualMachine)vm).
224
heapHisto(live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION);
225
drain(vm, in);
226
}
227
228
private static void dump(String pid, String options) throws IOException {
229
// parse the options to get the dump filename
230
String filename = parseDumpOptions(options);
231
if (filename == null) {
232
usage(1); // invalid options or no filename
233
}
234
235
// get the canonical path - important to avoid just passing
236
// a "heap.bin" and having the dump created in the target VM
237
// working directory rather than the directory where jmap
238
// is executed.
239
filename = new File(filename).getCanonicalPath();
240
241
// dump live objects only or not
242
boolean live = isDumpLiveObjects(options);
243
244
VirtualMachine vm = attach(pid);
245
System.out.println("Dumping heap to " + filename + " ...");
246
InputStream in = ((HotSpotVirtualMachine)vm).
247
dumpHeap((Object)filename,
248
(live ? LIVE_OBJECTS_OPTION : ALL_OBJECTS_OPTION));
249
drain(vm, in);
250
}
251
252
// Parse the options to the -dump option. Valid options are format=b and
253
// file=<file>. Returns <file> if provided. Returns null if <file> not
254
// provided, or invalid option.
255
private static String parseDumpOptions(String arg) {
256
assert arg.startsWith(DUMP_OPTION_PREFIX);
257
258
String filename = null;
259
260
// options are separated by comma (,)
261
String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(",");
262
263
for (int i=0; i<options.length; i++) {
264
String option = options[i];
265
266
if (option.equals("format=b")) {
267
// ignore format (not needed at this time)
268
} else if (option.equals("live")) {
269
// a valid suboption
270
} else {
271
272
// file=<file> - check that <file> is specified
273
if (option.startsWith("file=")) {
274
filename = option.substring(5);
275
if (filename.length() == 0) {
276
return null;
277
}
278
} else {
279
return null; // option not recognized
280
}
281
}
282
}
283
return filename;
284
}
285
286
private static boolean isDumpLiveObjects(String arg) {
287
// options are separated by comma (,)
288
String options[] = arg.substring(DUMP_OPTION_PREFIX.length()).split(",");
289
for (String suboption : options) {
290
if (suboption.equals("live")) {
291
return true;
292
}
293
}
294
return false;
295
}
296
297
// Attach to <pid>, existing if we fail to attach
298
private static VirtualMachine attach(String pid) {
299
try {
300
return VirtualMachine.attach(pid);
301
} catch (Exception x) {
302
String msg = x.getMessage();
303
if (msg != null) {
304
System.err.println(pid + ": " + msg);
305
} else {
306
x.printStackTrace();
307
}
308
if ((x instanceof AttachNotSupportedException) && haveSA()) {
309
System.err.println("The -F option can be used when the " +
310
"target process is not responding");
311
}
312
System.exit(1);
313
return null; // keep compiler happy
314
}
315
}
316
317
// Read the stream from the target VM until EOF, then detach
318
private static void drain(VirtualMachine vm, InputStream in) throws IOException {
319
// read to EOF and just print output
320
byte b[] = new byte[256];
321
int n;
322
do {
323
n = in.read(b);
324
if (n > 0) {
325
String s = new String(b, 0, n, "UTF-8");
326
System.out.print(s);
327
}
328
} while (n > 0);
329
in.close();
330
vm.detach();
331
}
332
333
// return a new string array with arg as the first element
334
private static String[] prepend(String arg, String args[]) {
335
String[] newargs = new String[args.length+1];
336
newargs[0] = arg;
337
System.arraycopy(args, 0, newargs, 1, args.length);
338
return newargs;
339
}
340
341
// returns true if SA is available
342
private static boolean haveSA() {
343
Class<?> c = loadClass("sun.jvm.hotspot.tools.HeapSummary");
344
return (c != null);
345
}
346
347
// print usage message
348
private static void usage(int exit) {
349
System.err.println("Usage:");
350
if (haveSA()) {
351
System.err.println(" jmap [option] <pid>");
352
System.err.println(" (to connect to running process)");
353
System.err.println(" jmap [option] <executable <core>");
354
System.err.println(" (to connect to a core file)");
355
System.err.println(" jmap [option] [server_id@]<remote server IP or hostname>");
356
System.err.println(" (to connect to remote debug server)");
357
System.err.println("");
358
System.err.println("where <option> is one of:");
359
System.err.println(" <none> to print same info as Solaris pmap");
360
System.err.println(" -heap to print java heap summary");
361
System.err.println(" -histo[:live] to print histogram of java object heap; if the \"live\"");
362
System.err.println(" suboption is specified, only count live objects");
363
System.err.println(" -clstats to print class loader statistics");
364
System.err.println(" -finalizerinfo to print information on objects awaiting finalization");
365
System.err.println(" -dump:<dump-options> to dump java heap in hprof binary format");
366
System.err.println(" dump-options:");
367
System.err.println(" live dump only live objects; if not specified,");
368
System.err.println(" all objects in the heap are dumped.");
369
System.err.println(" format=b binary format");
370
System.err.println(" file=<file> dump heap to <file>");
371
System.err.println(" Example: jmap -dump:live,format=b,file=heap.bin <pid>");
372
System.err.println(" -F force. Use with -dump:<dump-options> <pid> or -histo");
373
System.err.println(" to force a heap dump or histogram when <pid> does not");
374
System.err.println(" respond. The \"live\" suboption is not supported");
375
System.err.println(" in this mode.");
376
System.err.println(" -h | -help to print this help message");
377
System.err.println(" -J<flag> to pass <flag> directly to the runtime system");
378
} else {
379
System.err.println(" jmap -histo <pid>");
380
System.err.println(" (to connect to running process and print histogram of java object heap");
381
System.err.println(" jmap -dump:<dump-options> <pid>");
382
System.err.println(" (to connect to running process and dump java heap)");
383
System.err.println("");
384
System.err.println(" dump-options:");
385
System.err.println(" format=b binary default");
386
System.err.println(" file=<file> dump heap to <file>");
387
System.err.println("");
388
System.err.println(" Example: jmap -dump:format=b,file=heap.bin <pid>");
389
}
390
391
System.exit(exit);
392
}
393
}
394
395