Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.jcmd/share/classes/sun/tools/jmap/JMap.java
41159 views
1
/*
2
* Copyright (c) 2005, 2021, 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.io.File;
29
import java.io.IOException;
30
import java.io.InputStream;
31
import java.io.UnsupportedEncodingException;
32
import java.util.Collection;
33
34
import com.sun.tools.attach.VirtualMachine;
35
import com.sun.tools.attach.VirtualMachineDescriptor;
36
import com.sun.tools.attach.AttachNotSupportedException;
37
import sun.tools.attach.HotSpotVirtualMachine;
38
import sun.tools.common.ProcessArgumentMatcher;
39
40
/*
41
* This class is the main class for the JMap utility. It parses its arguments
42
* and decides if the command should be satisfied using the VM attach mechanism
43
* or an SA tool. At this time the only option that uses the VM attach mechanism
44
* is the -dump option to get a heap dump of a running application. All other
45
* options are mapped to SA tools.
46
*/
47
public class JMap {
48
49
public static void main(String[] args) throws Exception {
50
if (args.length == 0) {
51
usage(1); // no arguments
52
}
53
54
checkForUnsupportedOptions(args);
55
56
// the chosen option
57
String option = null;
58
59
// First iterate over the options (arguments starting with -). There should be
60
// one.
61
int optionCount = 0;
62
while (optionCount < args.length) {
63
String arg = args[optionCount];
64
if (!arg.startsWith("-")) {
65
break;
66
}
67
if (arg.equals("-?") ||
68
arg.equals("-h") ||
69
arg.equals("--help") ||
70
// -help: legacy. Undocumented.
71
arg.equals("-help")) {
72
usage(0);
73
} else {
74
if (option != null) {
75
usage(1); // option already specified
76
}
77
option = arg;
78
}
79
optionCount++;
80
}
81
82
// if no option provided then use default.
83
if (option == null) {
84
usage(0);
85
}
86
87
// Next we check the parameter count.
88
int paramCount = args.length - optionCount;
89
if (paramCount != 1) {
90
usage(1);
91
}
92
93
String pidArg = args[1];
94
// Here we handle the built-in options
95
// As more options are added we should create an abstract tool class and
96
// have a table to map the options
97
ProcessArgumentMatcher ap = new ProcessArgumentMatcher(pidArg);
98
Collection<String> pids = ap.getVirtualMachinePids(JMap.class);
99
100
if (pids.isEmpty()) {
101
System.err.println("Could not find any processes matching : '" + pidArg + "'");
102
System.exit(1);
103
}
104
105
for (String pid : pids) {
106
if (pids.size() > 1) {
107
System.out.println("Pid:" + pid);
108
}
109
if (option.equals("-histo")) {
110
histo(pid, "");
111
} else if (option.startsWith("-histo:")) {
112
histo(pid, option.substring("-histo:".length()));
113
} else if (option.startsWith("-dump:")) {
114
dump(pid, option.substring("-dump:".length()));
115
} else if (option.equals("-finalizerinfo")) {
116
executeCommandForPid(pid, "jcmd", "GC.finalizer_info");
117
} else if (option.equals("-clstats")) {
118
executeCommandForPid(pid, "jcmd", "VM.classloader_stats");
119
} else {
120
usage(1);
121
}
122
}
123
}
124
125
private static void executeCommandForPid(String pid, String command, Object ... args)
126
throws AttachNotSupportedException, IOException,
127
UnsupportedEncodingException {
128
VirtualMachine vm = VirtualMachine.attach(pid);
129
130
// Cast to HotSpotVirtualMachine as this is an
131
// implementation specific method.
132
HotSpotVirtualMachine hvm = (HotSpotVirtualMachine) vm;
133
try (InputStream in = hvm.executeCommand(command, args)) {
134
// read to EOF and just print output
135
byte b[] = new byte[256];
136
int n;
137
do {
138
n = in.read(b);
139
if (n > 0) {
140
String s = new String(b, 0, n, "UTF-8");
141
System.out.print(s);
142
}
143
} while (n > 0);
144
}
145
vm.detach();
146
}
147
148
private static String parseFileName(String opt) {
149
// opt starts with "file="
150
if (opt.length() > 5) {
151
// pass whole "file=" string
152
String filename = opt.substring(5);
153
try {
154
// Get the canonical path - important to avoid just
155
// passing a "heap.bin" and having the dump created
156
// in the target VM working directory rather than the
157
// directory where jmap is executed.
158
return new File(filename).getCanonicalPath();
159
} catch (IOException ioe) {
160
return null;
161
}
162
}
163
// no filename
164
return null;
165
}
166
167
private static void histo(String pid, String options)
168
throws AttachNotSupportedException, IOException,
169
UnsupportedEncodingException {
170
String liveopt = "-all";
171
String filename = null;
172
String parallel = null;
173
String subopts[] = options.split(",");
174
175
for (int i = 0; i < subopts.length; i++) {
176
String subopt = subopts[i];
177
if (subopt.equals("") || subopt.equals("all")) {
178
// pass
179
} else if (subopt.equals("live")) {
180
liveopt = "-live";
181
} else if (subopt.startsWith("file=")) {
182
filename = parseFileName(subopt);
183
if (filename == null) {
184
System.err.println("Fail: invalid option or no file name '" + subopt + "'");
185
usage(1);
186
}
187
} else if (subopt.startsWith("parallel=")) {
188
parallel = subopt.substring("parallel=".length());
189
if (parallel == null) {
190
System.err.println("Fail: no number provided in option: '" + subopt + "'");
191
usage(1);
192
}
193
} else {
194
System.err.println("Fail: invalid option: '" + subopt + "'");
195
usage(1);
196
}
197
}
198
199
System.out.flush();
200
201
// inspectHeap is not the same as jcmd GC.class_histogram
202
executeCommandForPid(pid, "inspectheap", liveopt, filename, parallel);
203
}
204
205
private static void dump(String pid, String options)
206
throws AttachNotSupportedException, IOException,
207
UnsupportedEncodingException {
208
209
String subopts[] = options.split(",");
210
String filename = null;
211
String liveopt = "-all";
212
String compress_level = null;
213
214
for (int i = 0; i < subopts.length; i++) {
215
String subopt = subopts[i];
216
if (subopt.equals("") || subopt.equals("all")) {
217
// pass
218
} else if (subopt.equals("live")) {
219
liveopt = "-live";
220
} else if (subopt.startsWith("file=")) {
221
filename = parseFileName(subopt);
222
if (filename == null) {
223
System.err.println("Fail: invalid option or no file name '" + subopt + "'");
224
usage(1);
225
}
226
} else if (subopt.equals("format=b")) {
227
// ignore format (not needed at this time)
228
} else if (subopt.startsWith("gz=")) {
229
compress_level = subopt.substring("gz=".length());
230
if (compress_level.length() == 0) {
231
System.err.println("Fail: no number provided in option: '" + subopt + "'");
232
usage(1);
233
}
234
} else {
235
System.err.println("Fail: invalid option: '" + subopt + "'");
236
usage(1);
237
}
238
}
239
240
if (filename == null) {
241
System.err.println("Fail: invalid option or no file name");
242
usage(1);
243
}
244
245
System.out.flush();
246
247
// dumpHeap is not the same as jcmd GC.heap_dump
248
executeCommandForPid(pid, "dumpheap", filename, liveopt, compress_level);
249
}
250
251
private static void checkForUnsupportedOptions(String[] args) {
252
// Check arguments for -F, -m, and non-numeric value
253
// and warn the user that SA is not supported anymore
254
255
int paramCount = 0;
256
257
for (String s : args) {
258
if (s.equals("-F")) {
259
SAOptionError("-F option used");
260
}
261
262
if (s.equals("-heap")) {
263
SAOptionError("-heap option used");
264
}
265
266
/* Reimplemented using jcmd, output format is different
267
from original one
268
269
if (s.equals("-clstats")) {
270
warnSA("-clstats option used");
271
}
272
273
if (s.equals("-finalizerinfo")) {
274
warnSA("-finalizerinfo option used");
275
}
276
*/
277
278
if (! s.startsWith("-")) {
279
paramCount += 1;
280
}
281
}
282
283
if (paramCount > 1) {
284
SAOptionError("More than one non-option argument");
285
}
286
}
287
288
private static void SAOptionError(String msg) {
289
System.err.println("Error: " + msg);
290
System.err.println("Cannot connect to core dump or remote debug server. Use jhsdb jmap instead");
291
System.exit(1);
292
}
293
294
// print usage message
295
private static void usage(int exit) {
296
System.err.println("Usage:");
297
System.err.println(" jmap -clstats <pid>");
298
System.err.println(" to connect to running process and print class loader statistics");
299
System.err.println(" jmap -finalizerinfo <pid>");
300
System.err.println(" to connect to running process and print information on objects awaiting finalization");
301
System.err.println(" jmap -histo[:[<histo-options>]] <pid>");
302
System.err.println(" to connect to running process and print histogram of java object heap");
303
System.err.println(" jmap -dump:<dump-options> <pid>");
304
System.err.println(" to connect to running process and dump java heap");
305
System.err.println(" jmap -? -h --help");
306
System.err.println(" to print this help message");
307
System.err.println("");
308
System.err.println(" dump-options:");
309
System.err.println(" live dump only live objects (takes precedence if both \"live\" and \"all\" are specified)");
310
System.err.println(" all dump all objects in the heap (default if one of \"live\" or \"all\" is not specified)");
311
System.err.println(" format=b binary format");
312
System.err.println(" file=<file> dump heap to <file>");
313
System.err.println(" gz=<number> If specified, the heap dump is written in gzipped format using the given compression level.");
314
System.err.println(" 1 (recommended) is the fastest, 9 the strongest compression.");
315
System.err.println("");
316
System.err.println(" Example: jmap -dump:live,format=b,file=heap.bin <pid>");
317
System.err.println("");
318
System.err.println(" histo-options:");
319
System.err.println(" live count only live objects (takes precedence if both \"live\" and \"all\" are specified)");
320
System.err.println(" all count all objects in the heap (default if one of \"live\" or \"all\" is not specified)");
321
System.err.println(" file=<file> dump data to <file>");
322
System.err.println(" parallel=<number> Number of parallel threads to use for heap inspection:");
323
System.err.println(" 0 (the default) means let the VM determine the number of threads to use");
324
System.err.println(" 1 means use one thread (disable parallelism).");
325
System.err.println(" For any other value the VM will try to use the specified number of threads, but might use fewer.");
326
System.err.println("");
327
System.err.println(" Example: jmap -histo:live,file=/tmp/histo.data <pid>");
328
System.exit(exit);
329
}
330
}
331
332