1 /* |
1 /* |
2 * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
143 } while (n > 0); |
143 } while (n > 0); |
144 } |
144 } |
145 vm.detach(); |
145 vm.detach(); |
146 } |
146 } |
147 |
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 |
148 private static void histo(String pid, String options) |
167 private static void histo(String pid, String options) |
149 throws AttachNotSupportedException, IOException, |
168 throws AttachNotSupportedException, IOException, |
150 UnsupportedEncodingException { |
169 UnsupportedEncodingException { |
151 String liveopt = "-all"; |
170 String liveopt = "-all"; |
152 if (options.isEmpty() || options.equals("all")) { |
171 String filename = null; |
153 // pass |
172 String subopts[] = options.split(","); |
154 } |
173 |
155 else if (options.equals("live")) { |
174 for (int i = 0; i < subopts.length; i++) { |
156 liveopt = "-live"; |
175 String subopt = subopts[i]; |
157 } |
176 if (subopt.equals("") || subopt.equals("all")) { |
158 else { |
177 // pass |
159 usage(1); |
178 } else if (subopt.equals("live")) { |
160 } |
179 liveopt = "-live"; |
|
180 } else if (subopt.startsWith("file=")) { |
|
181 filename = parseFileName(subopt); |
|
182 if (filename == null) { |
|
183 usage(1); // invalid options or no filename |
|
184 } |
|
185 } else { |
|
186 usage(1); |
|
187 } |
|
188 } |
|
189 |
|
190 System.out.flush(); |
161 |
191 |
162 // inspectHeap is not the same as jcmd GC.class_histogram |
192 // inspectHeap is not the same as jcmd GC.class_histogram |
163 executeCommandForPid(pid, "inspectheap", liveopt); |
193 executeCommandForPid(pid, "inspectheap", filename, liveopt); |
164 } |
194 } |
165 |
195 |
166 private static void dump(String pid, String options) |
196 private static void dump(String pid, String options) |
167 throws AttachNotSupportedException, IOException, |
197 throws AttachNotSupportedException, IOException, |
168 UnsupportedEncodingException { |
198 UnsupportedEncodingException { |
174 for (int i = 0; i < subopts.length; i++) { |
204 for (int i = 0; i < subopts.length; i++) { |
175 String subopt = subopts[i]; |
205 String subopt = subopts[i]; |
176 if (subopt.equals("live")) { |
206 if (subopt.equals("live")) { |
177 liveopt = "-live"; |
207 liveopt = "-live"; |
178 } else if (subopt.startsWith("file=")) { |
208 } else if (subopt.startsWith("file=")) { |
179 // file=<file> - check that <file> is specified |
209 filename = parseFileName(subopt); |
180 if (subopt.length() > 5) { |
|
181 filename = subopt.substring(5); |
|
182 } |
|
183 } |
210 } |
184 } |
211 } |
185 |
212 |
186 if (filename == null) { |
213 if (filename == null) { |
187 usage(1); // invalid options or no filename |
214 usage(1); // invalid options or no filename |
188 } |
215 } |
189 |
216 |
190 // get the canonical path - important to avoid just passing |
|
191 // a "heap.bin" and having the dump created in the target VM |
|
192 // working directory rather than the directory where jmap |
|
193 // is executed. |
|
194 filename = new File(filename).getCanonicalPath(); |
|
195 // dumpHeap is not the same as jcmd GC.heap_dump |
217 // dumpHeap is not the same as jcmd GC.heap_dump |
196 executeCommandForPid(pid, "dumpheap", filename, liveopt); |
218 executeCommandForPid(pid, "dumpheap", filename, liveopt); |
197 } |
219 } |
198 |
220 |
199 private static void checkForUnsupportedOptions(String[] args) { |
221 private static void checkForUnsupportedOptions(String[] args) { |
244 System.err.println("Usage:"); |
266 System.err.println("Usage:"); |
245 System.err.println(" jmap -clstats <pid>"); |
267 System.err.println(" jmap -clstats <pid>"); |
246 System.err.println(" to connect to running process and print class loader statistics"); |
268 System.err.println(" to connect to running process and print class loader statistics"); |
247 System.err.println(" jmap -finalizerinfo <pid>"); |
269 System.err.println(" jmap -finalizerinfo <pid>"); |
248 System.err.println(" to connect to running process and print information on objects awaiting finalization"); |
270 System.err.println(" to connect to running process and print information on objects awaiting finalization"); |
249 System.err.println(" jmap -histo[:live] <pid>"); |
271 System.err.println(" jmap -histo[:[<histo-options>]] <pid>"); |
250 System.err.println(" to connect to running process and print histogram of java object heap"); |
272 System.err.println(" to connect to running process and print histogram of java object heap"); |
251 System.err.println(" if the \"live\" suboption is specified, only count live objects"); |
|
252 System.err.println(" jmap -dump:<dump-options> <pid>"); |
273 System.err.println(" jmap -dump:<dump-options> <pid>"); |
253 System.err.println(" to connect to running process and dump java heap"); |
274 System.err.println(" to connect to running process and dump java heap"); |
254 System.err.println(" jmap -? -h --help"); |
275 System.err.println(" jmap -? -h --help"); |
255 System.err.println(" to print this help message"); |
276 System.err.println(" to print this help message"); |
256 System.err.println(""); |
277 System.err.println(""); |
257 System.err.println(" dump-options:"); |
278 System.err.println(" dump-options:"); |
258 System.err.println(" live dump only live objects; if not specified,"); |
279 System.err.println(" live dump only live objects"); |
259 System.err.println(" all objects in the heap are dumped."); |
280 System.err.println(" all dump all objects in the heap (default if one of \"live\" or \"all\" is not specified"); |
260 System.err.println(" format=b binary format"); |
281 System.err.println(" format=b binary format"); |
261 System.err.println(" file=<file> dump heap to <file>"); |
282 System.err.println(" file=<file> dump heap to <file>"); |
262 System.err.println(""); |
283 System.err.println(""); |
263 System.err.println(" Example: jmap -dump:live,format=b,file=heap.bin <pid>"); |
284 System.err.println(" Example: jmap -dump:live,format=b,file=heap.bin <pid>"); |
|
285 System.err.println(""); |
|
286 System.err.println(" histo-options:"); |
|
287 System.err.println(" live count only live objects"); |
|
288 System.err.println(" all count all objects in the heap (default if one of \"live\" or \"all\" is not specified)"); |
|
289 System.err.println(" file=<file> dump data to <file>"); |
|
290 System.err.println(""); |
|
291 System.err.println(" Example: jmap -histo:live,file=/tmp/histo.data <pid>"); |
264 System.exit(exit); |
292 System.exit(exit); |
265 } |
293 } |
266 } |
294 } |