Mercurial > hg > truffle
annotate src/share/vm/services/heapDumper.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | 30f67acf635d |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
2 * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. |
0 | 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. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_heapDumper.cpp.incl" | |
27 | |
28 /* | |
29 * HPROF binary format - description copied from: | |
30 * src/share/demo/jvmti/hprof/hprof_io.c | |
31 * | |
32 * | |
33 * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" | |
34 * (0-terminated) | |
35 * | |
36 * u4 size of identifiers. Identifiers are used to represent | |
37 * UTF8 strings, objects, stack traces, etc. They usually | |
38 * have the same size as host pointers. For example, on | |
39 * Solaris and Win32, the size is 4. | |
40 * u4 high word | |
41 * u4 low word number of milliseconds since 0:00 GMT, 1/1/70 | |
42 * [record]* a sequence of records. | |
43 * | |
44 * | |
45 * Record format: | |
46 * | |
47 * u1 a TAG denoting the type of the record | |
48 * u4 number of *microseconds* since the time stamp in the | |
49 * header. (wraps around in a little more than an hour) | |
50 * u4 number of bytes *remaining* in the record. Note that | |
51 * this number excludes the tag and the length field itself. | |
52 * [u1]* BODY of the record (a sequence of bytes) | |
53 * | |
54 * | |
55 * The following TAGs are supported: | |
56 * | |
57 * TAG BODY notes | |
58 *---------------------------------------------------------- | |
59 * HPROF_UTF8 a UTF8-encoded name | |
60 * | |
61 * id name ID | |
62 * [u1]* UTF8 characters (no trailing zero) | |
63 * | |
64 * HPROF_LOAD_CLASS a newly loaded class | |
65 * | |
66 * u4 class serial number (> 0) | |
67 * id class object ID | |
68 * u4 stack trace serial number | |
69 * id class name ID | |
70 * | |
71 * HPROF_UNLOAD_CLASS an unloading class | |
72 * | |
73 * u4 class serial_number | |
74 * | |
75 * HPROF_FRAME a Java stack frame | |
76 * | |
77 * id stack frame ID | |
78 * id method name ID | |
79 * id method signature ID | |
80 * id source file name ID | |
81 * u4 class serial number | |
82 * i4 line number. >0: normal | |
83 * -1: unknown | |
84 * -2: compiled method | |
85 * -3: native method | |
86 * | |
87 * HPROF_TRACE a Java stack trace | |
88 * | |
89 * u4 stack trace serial number | |
90 * u4 thread serial number | |
91 * u4 number of frames | |
92 * [id]* stack frame IDs | |
93 * | |
94 * | |
95 * HPROF_ALLOC_SITES a set of heap allocation sites, obtained after GC | |
96 * | |
97 * u2 flags 0x0001: incremental vs. complete | |
98 * 0x0002: sorted by allocation vs. live | |
99 * 0x0004: whether to force a GC | |
100 * u4 cutoff ratio | |
101 * u4 total live bytes | |
102 * u4 total live instances | |
103 * u8 total bytes allocated | |
104 * u8 total instances allocated | |
105 * u4 number of sites that follow | |
106 * [u1 is_array: 0: normal object | |
107 * 2: object array | |
108 * 4: boolean array | |
109 * 5: char array | |
110 * 6: float array | |
111 * 7: double array | |
112 * 8: byte array | |
113 * 9: short array | |
114 * 10: int array | |
115 * 11: long array | |
116 * u4 class serial number (may be zero during startup) | |
117 * u4 stack trace serial number | |
118 * u4 number of bytes alive | |
119 * u4 number of instances alive | |
120 * u4 number of bytes allocated | |
121 * u4]* number of instance allocated | |
122 * | |
123 * HPROF_START_THREAD a newly started thread. | |
124 * | |
125 * u4 thread serial number (> 0) | |
126 * id thread object ID | |
127 * u4 stack trace serial number | |
128 * id thread name ID | |
129 * id thread group name ID | |
130 * id thread group parent name ID | |
131 * | |
132 * HPROF_END_THREAD a terminating thread. | |
133 * | |
134 * u4 thread serial number | |
135 * | |
136 * HPROF_HEAP_SUMMARY heap summary | |
137 * | |
138 * u4 total live bytes | |
139 * u4 total live instances | |
140 * u8 total bytes allocated | |
141 * u8 total instances allocated | |
142 * | |
143 * HPROF_HEAP_DUMP denote a heap dump | |
144 * | |
145 * [heap dump sub-records]* | |
146 * | |
147 * There are four kinds of heap dump sub-records: | |
148 * | |
149 * u1 sub-record type | |
150 * | |
151 * HPROF_GC_ROOT_UNKNOWN unknown root | |
152 * | |
153 * id object ID | |
154 * | |
155 * HPROF_GC_ROOT_THREAD_OBJ thread object | |
156 * | |
157 * id thread object ID (may be 0 for a | |
158 * thread newly attached through JNI) | |
159 * u4 thread sequence number | |
160 * u4 stack trace sequence number | |
161 * | |
162 * HPROF_GC_ROOT_JNI_GLOBAL JNI global ref root | |
163 * | |
164 * id object ID | |
165 * id JNI global ref ID | |
166 * | |
167 * HPROF_GC_ROOT_JNI_LOCAL JNI local ref | |
168 * | |
169 * id object ID | |
170 * u4 thread serial number | |
171 * u4 frame # in stack trace (-1 for empty) | |
172 * | |
173 * HPROF_GC_ROOT_JAVA_FRAME Java stack frame | |
174 * | |
175 * id object ID | |
176 * u4 thread serial number | |
177 * u4 frame # in stack trace (-1 for empty) | |
178 * | |
179 * HPROF_GC_ROOT_NATIVE_STACK Native stack | |
180 * | |
181 * id object ID | |
182 * u4 thread serial number | |
183 * | |
184 * HPROF_GC_ROOT_STICKY_CLASS System class | |
185 * | |
186 * id object ID | |
187 * | |
188 * HPROF_GC_ROOT_THREAD_BLOCK Reference from thread block | |
189 * | |
190 * id object ID | |
191 * u4 thread serial number | |
192 * | |
193 * HPROF_GC_ROOT_MONITOR_USED Busy monitor | |
194 * | |
195 * id object ID | |
196 * | |
197 * HPROF_GC_CLASS_DUMP dump of a class object | |
198 * | |
199 * id class object ID | |
200 * u4 stack trace serial number | |
201 * id super class object ID | |
202 * id class loader object ID | |
203 * id signers object ID | |
204 * id protection domain object ID | |
205 * id reserved | |
206 * id reserved | |
207 * | |
208 * u4 instance size (in bytes) | |
209 * | |
210 * u2 size of constant pool | |
211 * [u2, constant pool index, | |
212 * ty, type | |
213 * 2: object | |
214 * 4: boolean | |
215 * 5: char | |
216 * 6: float | |
217 * 7: double | |
218 * 8: byte | |
219 * 9: short | |
220 * 10: int | |
221 * 11: long | |
222 * vl]* and value | |
223 * | |
224 * u2 number of static fields | |
225 * [id, static field name, | |
226 * ty, type, | |
227 * vl]* and value | |
228 * | |
229 * u2 number of inst. fields (not inc. super) | |
230 * [id, instance field name, | |
231 * ty]* type | |
232 * | |
233 * HPROF_GC_INSTANCE_DUMP dump of a normal object | |
234 * | |
235 * id object ID | |
236 * u4 stack trace serial number | |
237 * id class object ID | |
238 * u4 number of bytes that follow | |
239 * [vl]* instance field values (class, followed | |
240 * by super, super's super ...) | |
241 * | |
242 * HPROF_GC_OBJ_ARRAY_DUMP dump of an object array | |
243 * | |
244 * id array object ID | |
245 * u4 stack trace serial number | |
246 * u4 number of elements | |
247 * id array class ID | |
248 * [id]* elements | |
249 * | |
250 * HPROF_GC_PRIM_ARRAY_DUMP dump of a primitive array | |
251 * | |
252 * id array object ID | |
253 * u4 stack trace serial number | |
254 * u4 number of elements | |
255 * u1 element type | |
256 * 4: boolean array | |
257 * 5: char array | |
258 * 6: float array | |
259 * 7: double array | |
260 * 8: byte array | |
261 * 9: short array | |
262 * 10: int array | |
263 * 11: long array | |
264 * [u1]* elements | |
265 * | |
266 * HPROF_CPU_SAMPLES a set of sample traces of running threads | |
267 * | |
268 * u4 total number of samples | |
269 * u4 # of traces | |
270 * [u4 # of samples | |
271 * u4]* stack trace serial number | |
272 * | |
273 * HPROF_CONTROL_SETTINGS the settings of on/off switches | |
274 * | |
275 * u4 0x00000001: alloc traces on/off | |
276 * 0x00000002: cpu sampling on/off | |
277 * u2 stack trace depth | |
278 * | |
279 * | |
280 * When the header is "JAVA PROFILE 1.0.2" a heap dump can optionally | |
281 * be generated as a sequence of heap dump segments. This sequence is | |
282 * terminated by an end record. The additional tags allowed by format | |
283 * "JAVA PROFILE 1.0.2" are: | |
284 * | |
285 * HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment | |
286 * | |
287 * [heap dump sub-records]* | |
288 * The same sub-record types allowed by HPROF_HEAP_DUMP | |
289 * | |
290 * HPROF_HEAP_DUMP_END denotes the end of a heap dump | |
291 * | |
292 */ | |
293 | |
294 | |
295 // HPROF tags | |
296 | |
297 typedef enum { | |
298 // top-level records | |
299 HPROF_UTF8 = 0x01, | |
300 HPROF_LOAD_CLASS = 0x02, | |
301 HPROF_UNLOAD_CLASS = 0x03, | |
302 HPROF_FRAME = 0x04, | |
303 HPROF_TRACE = 0x05, | |
304 HPROF_ALLOC_SITES = 0x06, | |
305 HPROF_HEAP_SUMMARY = 0x07, | |
306 HPROF_START_THREAD = 0x0A, | |
307 HPROF_END_THREAD = 0x0B, | |
308 HPROF_HEAP_DUMP = 0x0C, | |
309 HPROF_CPU_SAMPLES = 0x0D, | |
310 HPROF_CONTROL_SETTINGS = 0x0E, | |
311 | |
312 // 1.0.2 record types | |
313 HPROF_HEAP_DUMP_SEGMENT = 0x1C, | |
314 HPROF_HEAP_DUMP_END = 0x2C, | |
315 | |
316 // field types | |
317 HPROF_ARRAY_OBJECT = 0x01, | |
318 HPROF_NORMAL_OBJECT = 0x02, | |
319 HPROF_BOOLEAN = 0x04, | |
320 HPROF_CHAR = 0x05, | |
321 HPROF_FLOAT = 0x06, | |
322 HPROF_DOUBLE = 0x07, | |
323 HPROF_BYTE = 0x08, | |
324 HPROF_SHORT = 0x09, | |
325 HPROF_INT = 0x0A, | |
326 HPROF_LONG = 0x0B, | |
327 | |
328 // data-dump sub-records | |
329 HPROF_GC_ROOT_UNKNOWN = 0xFF, | |
330 HPROF_GC_ROOT_JNI_GLOBAL = 0x01, | |
331 HPROF_GC_ROOT_JNI_LOCAL = 0x02, | |
332 HPROF_GC_ROOT_JAVA_FRAME = 0x03, | |
333 HPROF_GC_ROOT_NATIVE_STACK = 0x04, | |
334 HPROF_GC_ROOT_STICKY_CLASS = 0x05, | |
335 HPROF_GC_ROOT_THREAD_BLOCK = 0x06, | |
336 HPROF_GC_ROOT_MONITOR_USED = 0x07, | |
337 HPROF_GC_ROOT_THREAD_OBJ = 0x08, | |
338 HPROF_GC_CLASS_DUMP = 0x20, | |
339 HPROF_GC_INSTANCE_DUMP = 0x21, | |
340 HPROF_GC_OBJ_ARRAY_DUMP = 0x22, | |
341 HPROF_GC_PRIM_ARRAY_DUMP = 0x23 | |
342 } hprofTag; | |
343 | |
344 // Default stack trace ID (used for dummy HPROF_TRACE record) | |
345 enum { | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
346 STACK_TRACE_ID = 1, |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
347 INITIAL_CLASS_COUNT = 200 |
0 | 348 }; |
349 | |
350 // Supports I/O operations on a dump file | |
351 | |
352 class DumpWriter : public StackObj { | |
353 private: | |
354 enum { | |
355 io_buffer_size = 8*M | |
356 }; | |
357 | |
358 int _fd; // file descriptor (-1 if dump file not open) | |
359 jlong _bytes_written; // number of byte written to dump file | |
360 | |
361 char* _buffer; // internal buffer | |
362 int _size; | |
363 int _pos; | |
364 | |
365 char* _error; // error message when I/O fails | |
366 | |
367 void set_file_descriptor(int fd) { _fd = fd; } | |
368 int file_descriptor() const { return _fd; } | |
369 | |
370 char* buffer() const { return _buffer; } | |
371 int buffer_size() const { return _size; } | |
372 int position() const { return _pos; } | |
373 void set_position(int pos) { _pos = pos; } | |
374 | |
375 void set_error(const char* error) { _error = (char*)os::strdup(error); } | |
376 | |
377 // all I/O go through this function | |
378 void write_internal(void* s, int len); | |
379 | |
380 public: | |
381 DumpWriter(const char* path); | |
382 ~DumpWriter(); | |
383 | |
384 void close(); | |
385 bool is_open() const { return file_descriptor() >= 0; } | |
386 void flush(); | |
387 | |
388 // total number of bytes written to the disk | |
389 jlong bytes_written() const { return _bytes_written; } | |
390 | |
391 // adjust the number of bytes written to disk (used to keep the count | |
392 // of the number of bytes written in case of rewrites) | |
393 void adjust_bytes_written(jlong n) { _bytes_written += n; } | |
394 | |
395 // number of (buffered) bytes as yet unwritten to the dump file | |
396 jlong bytes_unwritten() const { return (jlong)position(); } | |
397 | |
398 char* error() const { return _error; } | |
399 | |
400 jlong current_offset(); | |
401 void seek_to_offset(jlong pos); | |
402 | |
403 // writer functions | |
404 void write_raw(void* s, int len); | |
405 void write_u1(u1 x) { write_raw((void*)&x, 1); } | |
406 void write_u2(u2 x); | |
407 void write_u4(u4 x); | |
408 void write_u8(u8 x); | |
409 void write_objectID(oop o); | |
410 void write_classID(Klass* k); | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
411 void write_id(u4 x); |
0 | 412 }; |
413 | |
414 DumpWriter::DumpWriter(const char* path) { | |
415 // try to allocate an I/O buffer of io_buffer_size. If there isn't | |
416 // sufficient memory then reduce size until we can allocate something. | |
417 _size = io_buffer_size; | |
418 do { | |
419 _buffer = (char*)os::malloc(_size); | |
420 if (_buffer == NULL) { | |
421 _size = _size >> 1; | |
422 } | |
423 } while (_buffer == NULL && _size > 0); | |
424 assert((_size > 0 && _buffer != NULL) || (_size == 0 && _buffer == NULL), "sanity check"); | |
425 _pos = 0; | |
426 _error = NULL; | |
427 _bytes_written = 0L; | |
428 _fd = os::create_binary_file(path, false); // don't replace existing file | |
429 | |
430 // if the open failed we record the error | |
431 if (_fd < 0) { | |
432 _error = (char*)os::strdup(strerror(errno)); | |
433 } | |
434 } | |
435 | |
436 DumpWriter::~DumpWriter() { | |
437 // flush and close dump file | |
438 if (file_descriptor() >= 0) { | |
439 close(); | |
440 } | |
441 if (_buffer != NULL) os::free(_buffer); | |
442 if (_error != NULL) os::free(_error); | |
443 } | |
444 | |
445 // closes dump file (if open) | |
446 void DumpWriter::close() { | |
447 // flush and close dump file | |
448 if (file_descriptor() >= 0) { | |
449 flush(); | |
450 ::close(file_descriptor()); | |
451 } | |
452 } | |
453 | |
454 // write directly to the file | |
455 void DumpWriter::write_internal(void* s, int len) { | |
456 if (is_open()) { | |
457 int n = ::write(file_descriptor(), s, len); | |
458 if (n > 0) { | |
459 _bytes_written += n; | |
460 } | |
461 if (n != len) { | |
462 if (n < 0) { | |
463 set_error(strerror(errno)); | |
464 } else { | |
465 set_error("file size limit"); | |
466 } | |
467 ::close(file_descriptor()); | |
468 set_file_descriptor(-1); | |
469 } | |
470 } | |
471 } | |
472 | |
473 // write raw bytes | |
474 void DumpWriter::write_raw(void* s, int len) { | |
475 if (is_open()) { | |
476 // flush buffer to make toom | |
477 if ((position()+ len) >= buffer_size()) { | |
478 flush(); | |
479 } | |
480 | |
481 // buffer not available or too big to buffer it | |
482 if ((buffer() == NULL) || (len >= buffer_size())) { | |
483 write_internal(s, len); | |
484 } else { | |
485 // Should optimize this for u1/u2/u4/u8 sizes. | |
486 memcpy(buffer() + position(), s, len); | |
487 set_position(position() + len); | |
488 } | |
489 } | |
490 } | |
491 | |
492 // flush any buffered bytes to the file | |
493 void DumpWriter::flush() { | |
494 if (is_open() && position() > 0) { | |
495 write_internal(buffer(), position()); | |
496 set_position(0); | |
497 } | |
498 } | |
499 | |
500 | |
501 jlong DumpWriter::current_offset() { | |
502 if (is_open()) { | |
503 // the offset is the file offset plus whatever we have buffered | |
504 jlong offset = os::current_file_offset(file_descriptor()); | |
505 assert(offset >= 0, "lseek failed"); | |
506 return offset + (jlong)position(); | |
507 } else { | |
508 return (jlong)-1; | |
509 } | |
510 } | |
511 | |
512 void DumpWriter::seek_to_offset(jlong off) { | |
513 assert(off >= 0, "bad offset"); | |
514 | |
515 // need to flush before seeking | |
516 flush(); | |
517 | |
518 // may be closed due to I/O error | |
519 if (is_open()) { | |
520 jlong n = os::seek_to_file_offset(file_descriptor(), off); | |
521 assert(n >= 0, "lseek failed"); | |
522 } | |
523 } | |
524 | |
525 void DumpWriter::write_u2(u2 x) { | |
526 u2 v; | |
527 Bytes::put_Java_u2((address)&v, x); | |
528 write_raw((void*)&v, 2); | |
529 } | |
530 | |
531 void DumpWriter::write_u4(u4 x) { | |
532 u4 v; | |
533 Bytes::put_Java_u4((address)&v, x); | |
534 write_raw((void*)&v, 4); | |
535 } | |
536 | |
537 void DumpWriter::write_u8(u8 x) { | |
538 u8 v; | |
539 Bytes::put_Java_u8((address)&v, x); | |
540 write_raw((void*)&v, 8); | |
541 } | |
542 | |
543 void DumpWriter::write_objectID(oop o) { | |
544 address a = (address)((uintptr_t)o); | |
545 #ifdef _LP64 | |
546 write_u8((u8)a); | |
547 #else | |
548 write_u4((u4)a); | |
549 #endif | |
550 } | |
551 | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
552 void DumpWriter::write_id(u4 x) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
553 #ifdef _LP64 |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
554 write_u8((u8) x); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
555 #else |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
556 write_u4(x); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
557 #endif |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
558 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
559 |
0 | 560 // We use java mirror as the class ID |
561 void DumpWriter::write_classID(Klass* k) { | |
562 write_objectID(k->java_mirror()); | |
563 } | |
564 | |
565 | |
566 | |
567 // Support class with a collection of functions used when dumping the heap | |
568 | |
569 class DumperSupport : AllStatic { | |
570 public: | |
571 | |
572 // write a header of the given type | |
573 static void write_header(DumpWriter* writer, hprofTag tag, u4 len); | |
574 | |
575 // returns hprof tag for the given type signature | |
576 static hprofTag sig2tag(symbolOop sig); | |
577 // returns hprof tag for the given basic type | |
578 static hprofTag type2tag(BasicType type); | |
579 | |
580 // returns the size of the instance of the given class | |
581 static u4 instance_size(klassOop k); | |
582 | |
583 // dump a jfloat | |
584 static void dump_float(DumpWriter* writer, jfloat f); | |
585 // dump a jdouble | |
586 static void dump_double(DumpWriter* writer, jdouble d); | |
587 // dumps the raw value of the given field | |
588 static void dump_field_value(DumpWriter* writer, char type, address addr); | |
589 // dumps static fields of the given class | |
590 static void dump_static_fields(DumpWriter* writer, klassOop k); | |
591 // dump the raw values of the instance fields of the given object | |
592 static void dump_instance_fields(DumpWriter* writer, oop o); | |
593 // dumps the definition of the instance fields for a given class | |
594 static void dump_instance_field_descriptors(DumpWriter* writer, klassOop k); | |
595 // creates HPROF_GC_INSTANCE_DUMP record for the given object | |
596 static void dump_instance(DumpWriter* writer, oop o); | |
597 // creates HPROF_GC_CLASS_DUMP record for the given class and each of its | |
598 // array classes | |
599 static void dump_class_and_array_classes(DumpWriter* writer, klassOop k); | |
600 // creates HPROF_GC_CLASS_DUMP record for a given primitive array | |
601 // class (and each multi-dimensional array class too) | |
602 static void dump_basic_type_array_class(DumpWriter* writer, klassOop k); | |
603 | |
604 // creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array | |
605 static void dump_object_array(DumpWriter* writer, objArrayOop array); | |
606 // creates HPROF_GC_PRIM_ARRAY_DUMP record for the given type array | |
607 static void dump_prim_array(DumpWriter* writer, typeArrayOop array); | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
608 // create HPROF_FRAME record for the given method and bci |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
609 static void dump_stack_frame(DumpWriter* writer, int frame_serial_num, int class_serial_num, methodOop m, int bci); |
0 | 610 }; |
611 | |
612 // write a header of the given type | |
613 void DumperSupport:: write_header(DumpWriter* writer, hprofTag tag, u4 len) { | |
614 writer->write_u1((u1)tag); | |
615 writer->write_u4(0); // current ticks | |
616 writer->write_u4(len); | |
617 } | |
618 | |
619 // returns hprof tag for the given type signature | |
620 hprofTag DumperSupport::sig2tag(symbolOop sig) { | |
621 switch (sig->byte_at(0)) { | |
622 case JVM_SIGNATURE_CLASS : return HPROF_NORMAL_OBJECT; | |
623 case JVM_SIGNATURE_ARRAY : return HPROF_NORMAL_OBJECT; | |
624 case JVM_SIGNATURE_BYTE : return HPROF_BYTE; | |
625 case JVM_SIGNATURE_CHAR : return HPROF_CHAR; | |
626 case JVM_SIGNATURE_FLOAT : return HPROF_FLOAT; | |
627 case JVM_SIGNATURE_DOUBLE : return HPROF_DOUBLE; | |
628 case JVM_SIGNATURE_INT : return HPROF_INT; | |
629 case JVM_SIGNATURE_LONG : return HPROF_LONG; | |
630 case JVM_SIGNATURE_SHORT : return HPROF_SHORT; | |
631 case JVM_SIGNATURE_BOOLEAN : return HPROF_BOOLEAN; | |
632 default : ShouldNotReachHere(); /* to shut up compiler */ return HPROF_BYTE; | |
633 } | |
634 } | |
635 | |
636 hprofTag DumperSupport::type2tag(BasicType type) { | |
637 switch (type) { | |
638 case T_BYTE : return HPROF_BYTE; | |
639 case T_CHAR : return HPROF_CHAR; | |
640 case T_FLOAT : return HPROF_FLOAT; | |
641 case T_DOUBLE : return HPROF_DOUBLE; | |
642 case T_INT : return HPROF_INT; | |
643 case T_LONG : return HPROF_LONG; | |
644 case T_SHORT : return HPROF_SHORT; | |
645 case T_BOOLEAN : return HPROF_BOOLEAN; | |
646 default : ShouldNotReachHere(); /* to shut up compiler */ return HPROF_BYTE; | |
647 } | |
648 } | |
649 | |
650 // dump a jfloat | |
651 void DumperSupport::dump_float(DumpWriter* writer, jfloat f) { | |
652 if (g_isnan(f)) { | |
653 writer->write_u4(0x7fc00000); // collapsing NaNs | |
654 } else { | |
655 union { | |
656 int i; | |
657 float f; | |
658 } u; | |
659 u.f = (float)f; | |
660 writer->write_u4((u4)u.i); | |
661 } | |
662 } | |
663 | |
664 // dump a jdouble | |
665 void DumperSupport::dump_double(DumpWriter* writer, jdouble d) { | |
666 union { | |
667 jlong l; | |
668 double d; | |
669 } u; | |
670 if (g_isnan(d)) { // collapsing NaNs | |
671 u.l = (jlong)(0x7ff80000); | |
672 u.l = (u.l << 32); | |
673 } else { | |
674 u.d = (double)d; | |
675 } | |
676 writer->write_u8((u8)u.l); | |
677 } | |
678 | |
679 // dumps the raw value of the given field | |
680 void DumperSupport::dump_field_value(DumpWriter* writer, char type, address addr) { | |
681 switch (type) { | |
682 case JVM_SIGNATURE_CLASS : | |
683 case JVM_SIGNATURE_ARRAY : { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
684 oop o; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
685 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
686 o = oopDesc::load_decode_heap_oop((narrowOop*)addr); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
687 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
688 o = oopDesc::load_decode_heap_oop((oop*)addr); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
689 } |
0 | 690 |
691 // reflection and sun.misc.Unsafe classes may have a reference to a | |
692 // klassOop so filter it out. | |
693 if (o != NULL && o->is_klass()) { | |
694 o = NULL; | |
695 } | |
696 | |
697 // FIXME: When sharing is enabled we don't emit field references to objects | |
698 // in shared spaces. We can remove this once we write records for the classes | |
699 // and strings that are shared. | |
700 if (o != NULL && o->is_shared()) { | |
701 o = NULL; | |
702 } | |
703 writer->write_objectID(o); | |
704 break; | |
705 } | |
706 case JVM_SIGNATURE_BYTE : { | |
707 jbyte* b = (jbyte*)addr; | |
708 writer->write_u1((u1)*b); | |
709 break; | |
710 } | |
711 case JVM_SIGNATURE_CHAR : { | |
712 jchar* c = (jchar*)addr; | |
713 writer->write_u2((u2)*c); | |
714 break; | |
715 } | |
716 case JVM_SIGNATURE_SHORT : { | |
717 jshort* s = (jshort*)addr; | |
718 writer->write_u2((u2)*s); | |
719 break; | |
720 } | |
721 case JVM_SIGNATURE_FLOAT : { | |
722 jfloat* f = (jfloat*)addr; | |
723 dump_float(writer, *f); | |
724 break; | |
725 } | |
726 case JVM_SIGNATURE_DOUBLE : { | |
727 jdouble* f = (jdouble*)addr; | |
728 dump_double(writer, *f); | |
729 break; | |
730 } | |
731 case JVM_SIGNATURE_INT : { | |
732 jint* i = (jint*)addr; | |
733 writer->write_u4((u4)*i); | |
734 break; | |
735 } | |
736 case JVM_SIGNATURE_LONG : { | |
737 jlong* l = (jlong*)addr; | |
738 writer->write_u8((u8)*l); | |
739 break; | |
740 } | |
741 case JVM_SIGNATURE_BOOLEAN : { | |
742 jboolean* b = (jboolean*)addr; | |
743 writer->write_u1((u1)*b); | |
744 break; | |
745 } | |
746 default : ShouldNotReachHere(); | |
747 } | |
748 } | |
749 | |
750 // returns the size of the instance of the given class | |
751 u4 DumperSupport::instance_size(klassOop k) { | |
752 HandleMark hm; | |
753 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); | |
754 | |
755 int size = 0; | |
756 | |
757 for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { | |
758 if (!fld.access_flags().is_static()) { | |
759 symbolOop sig = fld.signature(); | |
760 switch (sig->byte_at(0)) { | |
761 case JVM_SIGNATURE_CLASS : | |
762 case JVM_SIGNATURE_ARRAY : size += oopSize; break; | |
763 | |
764 case JVM_SIGNATURE_BYTE : | |
765 case JVM_SIGNATURE_BOOLEAN : size += 1; break; | |
766 | |
767 case JVM_SIGNATURE_CHAR : | |
768 case JVM_SIGNATURE_SHORT : size += 2; break; | |
769 | |
770 case JVM_SIGNATURE_INT : | |
771 case JVM_SIGNATURE_FLOAT : size += 4; break; | |
772 | |
773 case JVM_SIGNATURE_LONG : | |
774 case JVM_SIGNATURE_DOUBLE : size += 8; break; | |
775 | |
776 default : ShouldNotReachHere(); | |
777 } | |
778 } | |
779 } | |
780 return (u4)size; | |
781 } | |
782 | |
783 // dumps static fields of the given class | |
784 void DumperSupport::dump_static_fields(DumpWriter* writer, klassOop k) { | |
785 HandleMark hm; | |
786 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); | |
787 | |
788 // pass 1 - count the static fields | |
789 u2 field_count = 0; | |
790 for (FieldStream fldc(ikh, true, true); !fldc.eos(); fldc.next()) { | |
791 if (fldc.access_flags().is_static()) field_count++; | |
792 } | |
793 | |
794 writer->write_u2(field_count); | |
795 | |
796 // pass 2 - dump the field descriptors and raw values | |
797 for (FieldStream fld(ikh, true, true); !fld.eos(); fld.next()) { | |
798 if (fld.access_flags().is_static()) { | |
799 symbolOop sig = fld.signature(); | |
800 | |
801 writer->write_objectID(fld.name()); // name | |
802 writer->write_u1(sig2tag(sig)); // type | |
803 | |
804 // value | |
805 int offset = fld.offset(); | |
806 address addr = (address)k + offset; | |
807 | |
808 dump_field_value(writer, sig->byte_at(0), addr); | |
809 } | |
810 } | |
811 } | |
812 | |
813 // dump the raw values of the instance fields of the given object | |
814 void DumperSupport::dump_instance_fields(DumpWriter* writer, oop o) { | |
815 HandleMark hm; | |
816 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), o->klass()); | |
817 | |
818 for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { | |
819 if (!fld.access_flags().is_static()) { | |
820 symbolOop sig = fld.signature(); | |
821 address addr = (address)o + fld.offset(); | |
822 | |
823 dump_field_value(writer, sig->byte_at(0), addr); | |
824 } | |
825 } | |
826 } | |
827 | |
828 // dumps the definition of the instance fields for a given class | |
829 void DumperSupport::dump_instance_field_descriptors(DumpWriter* writer, klassOop k) { | |
830 HandleMark hm; | |
831 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); | |
832 | |
833 // pass 1 - count the instance fields | |
834 u2 field_count = 0; | |
835 for (FieldStream fldc(ikh, true, true); !fldc.eos(); fldc.next()) { | |
836 if (!fldc.access_flags().is_static()) field_count++; | |
837 } | |
838 | |
839 writer->write_u2(field_count); | |
840 | |
841 // pass 2 - dump the field descriptors | |
842 for (FieldStream fld(ikh, true, true); !fld.eos(); fld.next()) { | |
843 if (!fld.access_flags().is_static()) { | |
844 symbolOop sig = fld.signature(); | |
845 | |
846 writer->write_objectID(fld.name()); // name | |
847 writer->write_u1(sig2tag(sig)); // type | |
848 } | |
849 } | |
850 } | |
851 | |
852 // creates HPROF_GC_INSTANCE_DUMP record for the given object | |
853 void DumperSupport::dump_instance(DumpWriter* writer, oop o) { | |
854 klassOop k = o->klass(); | |
855 | |
856 writer->write_u1(HPROF_GC_INSTANCE_DUMP); | |
857 writer->write_objectID(o); | |
858 writer->write_u4(STACK_TRACE_ID); | |
859 | |
860 // class ID | |
861 writer->write_classID(Klass::cast(k)); | |
862 | |
863 // number of bytes that follow | |
864 writer->write_u4(instance_size(k) ); | |
865 | |
866 // field values | |
867 dump_instance_fields(writer, o); | |
868 } | |
869 | |
870 // creates HPROF_GC_CLASS_DUMP record for the given class and each of | |
871 // its array classes | |
872 void DumperSupport::dump_class_and_array_classes(DumpWriter* writer, klassOop k) { | |
873 Klass* klass = Klass::cast(k); | |
874 assert(klass->oop_is_instance(), "not an instanceKlass"); | |
875 instanceKlass* ik = (instanceKlass*)klass; | |
876 | |
877 writer->write_u1(HPROF_GC_CLASS_DUMP); | |
878 | |
879 // class ID | |
880 writer->write_classID(ik); | |
881 writer->write_u4(STACK_TRACE_ID); | |
882 | |
883 // super class ID | |
884 klassOop java_super = ik->java_super(); | |
885 if (java_super == NULL) { | |
886 writer->write_objectID(NULL); | |
887 } else { | |
888 writer->write_classID(Klass::cast(java_super)); | |
889 } | |
890 | |
891 writer->write_objectID(ik->class_loader()); | |
892 writer->write_objectID(ik->signers()); | |
893 writer->write_objectID(ik->protection_domain()); | |
894 | |
895 // reserved | |
896 writer->write_objectID(NULL); | |
897 writer->write_objectID(NULL); | |
898 | |
899 // instance size | |
900 writer->write_u4(DumperSupport::instance_size(k)); | |
901 | |
902 // size of constant pool - ignored by HAT 1.1 | |
903 writer->write_u2(0); | |
904 | |
905 // number of static fields | |
906 dump_static_fields(writer, k); | |
907 | |
908 // description of instance fields | |
909 dump_instance_field_descriptors(writer, k); | |
910 | |
911 // array classes | |
912 k = klass->array_klass_or_null(); | |
913 while (k != NULL) { | |
914 Klass* klass = Klass::cast(k); | |
915 assert(klass->oop_is_objArray(), "not an objArrayKlass"); | |
916 | |
917 writer->write_u1(HPROF_GC_CLASS_DUMP); | |
918 writer->write_classID(klass); | |
919 writer->write_u4(STACK_TRACE_ID); | |
920 | |
921 // super class of array classes is java.lang.Object | |
922 java_super = klass->java_super(); | |
923 assert(java_super != NULL, "checking"); | |
924 writer->write_classID(Klass::cast(java_super)); | |
925 | |
926 writer->write_objectID(ik->class_loader()); | |
927 writer->write_objectID(ik->signers()); | |
928 writer->write_objectID(ik->protection_domain()); | |
929 | |
930 writer->write_objectID(NULL); // reserved | |
931 writer->write_objectID(NULL); | |
932 writer->write_u4(0); // instance size | |
933 writer->write_u2(0); // constant pool | |
934 writer->write_u2(0); // static fields | |
935 writer->write_u2(0); // instance fields | |
936 | |
937 // get the array class for the next rank | |
938 k = klass->array_klass_or_null(); | |
939 } | |
940 } | |
941 | |
942 // creates HPROF_GC_CLASS_DUMP record for a given primitive array | |
943 // class (and each multi-dimensional array class too) | |
944 void DumperSupport::dump_basic_type_array_class(DumpWriter* writer, klassOop k) { | |
945 // array classes | |
946 while (k != NULL) { | |
947 Klass* klass = Klass::cast(k); | |
948 | |
949 writer->write_u1(HPROF_GC_CLASS_DUMP); | |
950 writer->write_classID(klass); | |
951 writer->write_u4(STACK_TRACE_ID); | |
952 | |
953 // super class of array classes is java.lang.Object | |
954 klassOop java_super = klass->java_super(); | |
955 assert(java_super != NULL, "checking"); | |
956 writer->write_classID(Klass::cast(java_super)); | |
957 | |
958 writer->write_objectID(NULL); // loader | |
959 writer->write_objectID(NULL); // signers | |
960 writer->write_objectID(NULL); // protection domain | |
961 | |
962 writer->write_objectID(NULL); // reserved | |
963 writer->write_objectID(NULL); | |
964 writer->write_u4(0); // instance size | |
965 writer->write_u2(0); // constant pool | |
966 writer->write_u2(0); // static fields | |
967 writer->write_u2(0); // instance fields | |
968 | |
969 // get the array class for the next rank | |
970 k = klass->array_klass_or_null(); | |
971 } | |
972 } | |
973 | |
974 // creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array | |
975 void DumperSupport::dump_object_array(DumpWriter* writer, objArrayOop array) { | |
976 | |
977 // filter this | |
978 if (array->klass() == Universe::systemObjArrayKlassObj()) return; | |
979 | |
980 writer->write_u1(HPROF_GC_OBJ_ARRAY_DUMP); | |
981 writer->write_objectID(array); | |
982 writer->write_u4(STACK_TRACE_ID); | |
983 writer->write_u4((u4)array->length()); | |
984 | |
985 // array class ID | |
986 writer->write_classID(Klass::cast(array->klass())); | |
987 | |
988 // [id]* elements | |
989 for (int index=0; index<array->length(); index++) { | |
990 oop o = array->obj_at(index); | |
991 writer->write_objectID(o); | |
992 } | |
993 } | |
994 | |
995 #define WRITE_ARRAY(Array, Type, Size) \ | |
996 for (int i=0; i<Array->length(); i++) { writer->write_##Size((Size)array->Type##_at(i)); } | |
997 | |
998 | |
999 // creates HPROF_GC_PRIM_ARRAY_DUMP record for the given type array | |
1000 void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { | |
1001 BasicType type = typeArrayKlass::cast(array->klass())->element_type(); | |
1002 | |
1003 writer->write_u1(HPROF_GC_PRIM_ARRAY_DUMP); | |
1004 writer->write_objectID(array); | |
1005 writer->write_u4(STACK_TRACE_ID); | |
1006 writer->write_u4((u4)array->length()); | |
1007 writer->write_u1(type2tag(type)); | |
1008 | |
1009 // nothing to copy | |
1010 if (array->length() == 0) { | |
1011 return; | |
1012 } | |
1013 | |
1014 // If the byte ordering is big endian then we can copy most types directly | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
1015 int length_in_bytes = array->length() * type2aelembytes(type); |
0 | 1016 assert(length_in_bytes > 0, "nothing to copy"); |
1017 | |
1018 switch (type) { | |
1019 case T_INT : { | |
1020 if (Bytes::is_Java_byte_ordering_different()) { | |
1021 WRITE_ARRAY(array, int, u4); | |
1022 } else { | |
1023 writer->write_raw((void*)(array->int_at_addr(0)), length_in_bytes); | |
1024 } | |
1025 break; | |
1026 } | |
1027 case T_BYTE : { | |
1028 writer->write_raw((void*)(array->byte_at_addr(0)), length_in_bytes); | |
1029 break; | |
1030 } | |
1031 case T_CHAR : { | |
1032 if (Bytes::is_Java_byte_ordering_different()) { | |
1033 WRITE_ARRAY(array, char, u2); | |
1034 } else { | |
1035 writer->write_raw((void*)(array->char_at_addr(0)), length_in_bytes); | |
1036 } | |
1037 break; | |
1038 } | |
1039 case T_SHORT : { | |
1040 if (Bytes::is_Java_byte_ordering_different()) { | |
1041 WRITE_ARRAY(array, short, u2); | |
1042 } else { | |
1043 writer->write_raw((void*)(array->short_at_addr(0)), length_in_bytes); | |
1044 } | |
1045 break; | |
1046 } | |
1047 case T_BOOLEAN : { | |
1048 if (Bytes::is_Java_byte_ordering_different()) { | |
1049 WRITE_ARRAY(array, bool, u1); | |
1050 } else { | |
1051 writer->write_raw((void*)(array->bool_at_addr(0)), length_in_bytes); | |
1052 } | |
1053 break; | |
1054 } | |
1055 case T_LONG : { | |
1056 if (Bytes::is_Java_byte_ordering_different()) { | |
1057 WRITE_ARRAY(array, long, u8); | |
1058 } else { | |
1059 writer->write_raw((void*)(array->long_at_addr(0)), length_in_bytes); | |
1060 } | |
1061 break; | |
1062 } | |
1063 | |
1064 // handle float/doubles in a special value to ensure than NaNs are | |
1065 // written correctly. TO DO: Check if we can avoid this on processors that | |
1066 // use IEEE 754. | |
1067 | |
1068 case T_FLOAT : { | |
1069 for (int i=0; i<array->length(); i++) { | |
1070 dump_float( writer, array->float_at(i) ); | |
1071 } | |
1072 break; | |
1073 } | |
1074 case T_DOUBLE : { | |
1075 for (int i=0; i<array->length(); i++) { | |
1076 dump_double( writer, array->double_at(i) ); | |
1077 } | |
1078 break; | |
1079 } | |
1080 default : ShouldNotReachHere(); | |
1081 } | |
1082 } | |
1083 | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1084 // create a HPROF_FRAME record of the given methodOop and bci |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1085 void DumperSupport::dump_stack_frame(DumpWriter* writer, |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1086 int frame_serial_num, |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1087 int class_serial_num, |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1088 methodOop m, |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1089 int bci) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1090 int line_number; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1091 if (m->is_native()) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1092 line_number = -3; // native frame |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1093 } else { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1094 line_number = m->line_number_from_bci(bci); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1095 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1096 |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1097 write_header(writer, HPROF_FRAME, 4*oopSize + 2*sizeof(u4)); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1098 writer->write_id(frame_serial_num); // frame serial number |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1099 writer->write_objectID(m->name()); // method's name |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1100 writer->write_objectID(m->signature()); // method's signature |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1101 |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1102 assert(Klass::cast(m->method_holder())->oop_is_instance(), "not instanceKlass"); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1103 writer->write_objectID(instanceKlass::cast(m->method_holder())->source_file_name()); // source file name |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1104 writer->write_u4(class_serial_num); // class serial number |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1105 writer->write_u4((u4) line_number); // line number |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1106 } |
0 | 1107 |
1108 // Support class used to generate HPROF_UTF8 records from the entries in the | |
1109 // SymbolTable. | |
1110 | |
1111 class SymbolTableDumper : public OopClosure { | |
1112 private: | |
1113 DumpWriter* _writer; | |
1114 DumpWriter* writer() const { return _writer; } | |
1115 public: | |
1116 SymbolTableDumper(DumpWriter* writer) { _writer = writer; } | |
1117 void do_oop(oop* obj_p); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
1118 void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } |
0 | 1119 }; |
1120 | |
1121 void SymbolTableDumper::do_oop(oop* obj_p) { | |
1122 ResourceMark rm; | |
1123 symbolOop sym = (symbolOop)*obj_p; | |
1124 | |
1125 int len = sym->utf8_length(); | |
1126 if (len > 0) { | |
1127 char* s = sym->as_utf8(); | |
1128 DumperSupport::write_header(writer(), HPROF_UTF8, oopSize + len); | |
1129 writer()->write_objectID(sym); | |
1130 writer()->write_raw(s, len); | |
1131 } | |
1132 } | |
1133 | |
1134 | |
1135 // Support class used to generate HPROF_GC_ROOT_JNI_LOCAL records | |
1136 | |
1137 class JNILocalsDumper : public OopClosure { | |
1138 private: | |
1139 DumpWriter* _writer; | |
1140 u4 _thread_serial_num; | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1141 int _frame_num; |
0 | 1142 DumpWriter* writer() const { return _writer; } |
1143 public: | |
1144 JNILocalsDumper(DumpWriter* writer, u4 thread_serial_num) { | |
1145 _writer = writer; | |
1146 _thread_serial_num = thread_serial_num; | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1147 _frame_num = -1; // default - empty stack |
0 | 1148 } |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1149 void set_frame_number(int n) { _frame_num = n; } |
0 | 1150 void do_oop(oop* obj_p); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
1151 void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } |
0 | 1152 }; |
1153 | |
1154 | |
1155 void JNILocalsDumper::do_oop(oop* obj_p) { | |
1156 // ignore null or deleted handles | |
1157 oop o = *obj_p; | |
1158 if (o != NULL && o != JNIHandles::deleted_handle()) { | |
1159 writer()->write_u1(HPROF_GC_ROOT_JNI_LOCAL); | |
1160 writer()->write_objectID(o); | |
1161 writer()->write_u4(_thread_serial_num); | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1162 writer()->write_u4((u4)_frame_num); |
0 | 1163 } |
1164 } | |
1165 | |
1166 | |
1167 // Support class used to generate HPROF_GC_ROOT_JNI_GLOBAL records | |
1168 | |
1169 class JNIGlobalsDumper : public OopClosure { | |
1170 private: | |
1171 DumpWriter* _writer; | |
1172 DumpWriter* writer() const { return _writer; } | |
1173 | |
1174 public: | |
1175 JNIGlobalsDumper(DumpWriter* writer) { | |
1176 _writer = writer; | |
1177 } | |
1178 void do_oop(oop* obj_p); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
1179 void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } |
0 | 1180 }; |
1181 | |
1182 void JNIGlobalsDumper::do_oop(oop* obj_p) { | |
1183 oop o = *obj_p; | |
1184 | |
1185 // ignore these | |
1186 if (o == NULL || o == JNIHandles::deleted_handle()) return; | |
1187 | |
1188 // we ignore global ref to symbols and other internal objects | |
1189 if (o->is_instance() || o->is_objArray() || o->is_typeArray()) { | |
1190 writer()->write_u1(HPROF_GC_ROOT_JNI_GLOBAL); | |
1191 writer()->write_objectID(o); | |
1192 writer()->write_objectID((oopDesc*)obj_p); // global ref ID | |
1193 } | |
1194 }; | |
1195 | |
1196 | |
1197 // Support class used to generate HPROF_GC_ROOT_MONITOR_USED records | |
1198 | |
1199 class MonitorUsedDumper : public OopClosure { | |
1200 private: | |
1201 DumpWriter* _writer; | |
1202 DumpWriter* writer() const { return _writer; } | |
1203 public: | |
1204 MonitorUsedDumper(DumpWriter* writer) { | |
1205 _writer = writer; | |
1206 } | |
1207 void do_oop(oop* obj_p) { | |
1208 writer()->write_u1(HPROF_GC_ROOT_MONITOR_USED); | |
1209 writer()->write_objectID(*obj_p); | |
1210 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
1211 void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } |
0 | 1212 }; |
1213 | |
1214 | |
1215 // Support class used to generate HPROF_GC_ROOT_STICKY_CLASS records | |
1216 | |
1217 class StickyClassDumper : public OopClosure { | |
1218 private: | |
1219 DumpWriter* _writer; | |
1220 DumpWriter* writer() const { return _writer; } | |
1221 public: | |
1222 StickyClassDumper(DumpWriter* writer) { | |
1223 _writer = writer; | |
1224 } | |
1225 void do_oop(oop* obj_p); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
29
diff
changeset
|
1226 void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } |
0 | 1227 }; |
1228 | |
1229 void StickyClassDumper::do_oop(oop* obj_p) { | |
1230 if (*obj_p != NULL) { | |
1231 oop o = *obj_p; | |
1232 if (o->is_klass()) { | |
1233 klassOop k = klassOop(o); | |
1234 if (Klass::cast(k)->oop_is_instance()) { | |
1235 instanceKlass* ik = instanceKlass::cast(k); | |
1236 writer()->write_u1(HPROF_GC_ROOT_STICKY_CLASS); | |
1237 writer()->write_classID(ik); | |
1238 } | |
1239 } | |
1240 } | |
1241 } | |
1242 | |
1243 | |
1244 class VM_HeapDumper; | |
1245 | |
1246 // Support class using when iterating over the heap. | |
1247 | |
1248 class HeapObjectDumper : public ObjectClosure { | |
1249 private: | |
1250 VM_HeapDumper* _dumper; | |
1251 DumpWriter* _writer; | |
1252 | |
1253 VM_HeapDumper* dumper() { return _dumper; } | |
1254 DumpWriter* writer() { return _writer; } | |
1255 | |
1256 // used to indicate that a record has been writen | |
1257 void mark_end_of_record(); | |
1258 | |
1259 public: | |
1260 HeapObjectDumper(VM_HeapDumper* dumper, DumpWriter* writer) { | |
1261 _dumper = dumper; | |
1262 _writer = writer; | |
1263 } | |
1264 | |
1265 // called for each object in the heap | |
1266 void do_object(oop o); | |
1267 }; | |
1268 | |
1269 void HeapObjectDumper::do_object(oop o) { | |
1270 // hide the sentinel for deleted handles | |
1271 if (o == JNIHandles::deleted_handle()) return; | |
1272 | |
1273 // ignore KlassKlass objects | |
1274 if (o->is_klass()) return; | |
1275 | |
1276 // skip classes as these emitted as HPROF_GC_CLASS_DUMP records | |
1142 | 1277 if (o->klass() == SystemDictionary::Class_klass()) { |
0 | 1278 if (!java_lang_Class::is_primitive(o)) { |
1279 return; | |
1280 } | |
1281 } | |
1282 | |
1283 // create a HPROF_GC_INSTANCE record for each object | |
1284 if (o->is_instance()) { | |
1285 DumperSupport::dump_instance(writer(), o); | |
1286 mark_end_of_record(); | |
1287 } else { | |
1288 // create a HPROF_GC_OBJ_ARRAY_DUMP record for each object array | |
1289 if (o->is_objArray()) { | |
1290 DumperSupport::dump_object_array(writer(), objArrayOop(o)); | |
1291 mark_end_of_record(); | |
1292 } else { | |
1293 // create a HPROF_GC_PRIM_ARRAY_DUMP record for each type array | |
1294 if (o->is_typeArray()) { | |
1295 DumperSupport::dump_prim_array(writer(), typeArrayOop(o)); | |
1296 mark_end_of_record(); | |
1297 } | |
1298 } | |
1299 } | |
1300 } | |
1301 | |
1302 // The VM operation that performs the heap dump | |
1303 class VM_HeapDumper : public VM_GC_Operation { | |
1304 private: | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1305 static VM_HeapDumper* _global_dumper; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1306 static DumpWriter* _global_writer; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1307 DumpWriter* _local_writer; |
0 | 1308 bool _gc_before_heap_dump; |
1309 bool _is_segmented_dump; | |
1310 jlong _dump_start; | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1311 GrowableArray<Klass*>* _klass_map; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1312 ThreadStackTrace** _stack_traces; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1313 int _num_threads; |
0 | 1314 |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1315 // accessors and setters |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1316 static VM_HeapDumper* dumper() { assert(_global_dumper != NULL, "Error"); return _global_dumper; } |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1317 static DumpWriter* writer() { assert(_global_writer != NULL, "Error"); return _global_writer; } |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1318 void set_global_dumper() { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1319 assert(_global_dumper == NULL, "Error"); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1320 _global_dumper = this; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1321 } |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1322 void set_global_writer() { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1323 assert(_global_writer == NULL, "Error"); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1324 _global_writer = _local_writer; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1325 } |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1326 void clear_global_dumper() { _global_dumper = NULL; } |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1327 void clear_global_writer() { _global_writer = NULL; } |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1328 |
0 | 1329 bool is_segmented_dump() const { return _is_segmented_dump; } |
1330 void set_segmented_dump() { _is_segmented_dump = true; } | |
1331 jlong dump_start() const { return _dump_start; } | |
1332 void set_dump_start(jlong pos); | |
1333 | |
1334 bool skip_operation() const; | |
1335 | |
1336 // writes a HPROF_LOAD_CLASS record | |
1337 static void do_load_class(klassOop k); | |
1338 | |
1339 // writes a HPROF_GC_CLASS_DUMP record for the given class | |
1340 // (and each array class too) | |
1341 static void do_class_dump(klassOop k); | |
1342 | |
1343 // writes a HPROF_GC_CLASS_DUMP records for a given basic type | |
1344 // array (and each multi-dimensional array too) | |
1345 static void do_basic_type_array_class_dump(klassOop k); | |
1346 | |
1347 // HPROF_GC_ROOT_THREAD_OBJ records | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1348 int do_thread(JavaThread* thread, u4 thread_serial_num); |
0 | 1349 void do_threads(); |
1350 | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1351 void add_class_serial_number(Klass* k, int serial_num) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1352 _klass_map->at_put_grow(serial_num, k); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1353 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1354 |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1355 // HPROF_TRACE and HPROF_FRAME records |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1356 void dump_stack_traces(); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1357 |
0 | 1358 // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record |
1359 void write_dump_header(); | |
1360 | |
1361 // fixes up the length of the current dump record | |
1362 void write_current_dump_record_length(); | |
1363 | |
1364 // fixes up the current dump record )and writes HPROF_HEAP_DUMP_END | |
1365 // record in the case of a segmented heap dump) | |
1366 void end_of_dump(); | |
1367 | |
1368 public: | |
1369 VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump) : | |
1370 VM_GC_Operation(0 /* total collections, dummy, ignored */, | |
1371 0 /* total full collections, dummy, ignored */, | |
1372 gc_before_heap_dump) { | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1373 _local_writer = writer; |
0 | 1374 _gc_before_heap_dump = gc_before_heap_dump; |
1375 _is_segmented_dump = false; | |
1376 _dump_start = (jlong)-1; | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1377 _klass_map = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, true); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1378 _stack_traces = NULL; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1379 _num_threads = 0; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1380 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1381 ~VM_HeapDumper() { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1382 if (_stack_traces != NULL) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1383 for (int i=0; i < _num_threads; i++) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1384 delete _stack_traces[i]; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1385 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1386 FREE_C_HEAP_ARRAY(ThreadStackTrace*, _stack_traces); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1387 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1388 delete _klass_map; |
0 | 1389 } |
1390 | |
1391 VMOp_Type type() const { return VMOp_HeapDumper; } | |
1392 // used to mark sub-record boundary | |
1393 void check_segment_length(); | |
1394 void doit(); | |
1395 }; | |
1396 | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1397 VM_HeapDumper* VM_HeapDumper::_global_dumper = NULL; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1398 DumpWriter* VM_HeapDumper::_global_writer = NULL; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1399 |
0 | 1400 bool VM_HeapDumper::skip_operation() const { |
1401 return false; | |
1402 } | |
1403 | |
1404 // sets the dump starting position | |
1405 void VM_HeapDumper::set_dump_start(jlong pos) { | |
1406 _dump_start = pos; | |
1407 } | |
1408 | |
1409 // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record | |
1410 void VM_HeapDumper::write_dump_header() { | |
1411 if (writer()->is_open()) { | |
1412 if (is_segmented_dump()) { | |
1413 writer()->write_u1(HPROF_HEAP_DUMP_SEGMENT); | |
1414 } else { | |
1415 writer()->write_u1(HPROF_HEAP_DUMP); | |
1416 } | |
1417 writer()->write_u4(0); // current ticks | |
1418 | |
1419 // record the starting position for the dump (its length will be fixed up later) | |
1420 set_dump_start(writer()->current_offset()); | |
1421 writer()->write_u4(0); | |
1422 } | |
1423 } | |
1424 | |
1425 // fixes up the length of the current dump record | |
1426 void VM_HeapDumper::write_current_dump_record_length() { | |
1427 if (writer()->is_open()) { | |
1428 assert(dump_start() >= 0, "no dump start recorded"); | |
1429 | |
1430 // calculate the size of the dump record | |
1431 jlong dump_end = writer()->current_offset(); | |
1432 jlong dump_len = (dump_end - dump_start() - 4); | |
1433 | |
1434 // record length must fit in a u4 | |
1435 if (dump_len > (jlong)(4L*(jlong)G)) { | |
1436 warning("record is too large"); | |
1437 } | |
1438 | |
1439 // seek to the dump start and fix-up the length | |
1440 writer()->seek_to_offset(dump_start()); | |
1441 writer()->write_u4((u4)dump_len); | |
1442 | |
1443 // adjust the total size written to keep the bytes written correct. | |
1444 writer()->adjust_bytes_written(-((long) sizeof(u4))); | |
1445 | |
1446 // seek to dump end so we can continue | |
1447 writer()->seek_to_offset(dump_end); | |
1448 | |
1449 // no current dump record | |
1450 set_dump_start((jlong)-1); | |
1451 } | |
1452 } | |
1453 | |
1454 // used on a sub-record boundary to check if we need to start a | |
1455 // new segment. | |
1456 void VM_HeapDumper::check_segment_length() { | |
1457 if (writer()->is_open()) { | |
1458 if (is_segmented_dump()) { | |
1459 // don't use current_offset that would be too expensive on a per record basis | |
1460 jlong dump_end = writer()->bytes_written() + writer()->bytes_unwritten(); | |
1461 assert(dump_end == writer()->current_offset(), "checking"); | |
1462 jlong dump_len = (dump_end - dump_start() - 4); | |
1463 assert(dump_len >= 0 && dump_len <= max_juint, "bad dump length"); | |
1464 | |
1465 if (dump_len > (jlong)HeapDumpSegmentSize) { | |
1466 write_current_dump_record_length(); | |
1467 write_dump_header(); | |
1468 } | |
1469 } | |
1470 } | |
1471 } | |
1472 | |
1473 // fixes up the current dump record )and writes HPROF_HEAP_DUMP_END | |
1474 // record in the case of a segmented heap dump) | |
1475 void VM_HeapDumper::end_of_dump() { | |
1476 if (writer()->is_open()) { | |
1477 write_current_dump_record_length(); | |
1478 | |
1479 // for segmented dump we write the end record | |
1480 if (is_segmented_dump()) { | |
1481 writer()->write_u1(HPROF_HEAP_DUMP_END); | |
1482 writer()->write_u4(0); | |
1483 writer()->write_u4(0); | |
1484 } | |
1485 } | |
1486 } | |
1487 | |
1488 // marks sub-record boundary | |
1489 void HeapObjectDumper::mark_end_of_record() { | |
1490 dumper()->check_segment_length(); | |
1491 } | |
1492 | |
1493 // writes a HPROF_LOAD_CLASS record for the class (and each of its | |
1494 // array classes) | |
1495 void VM_HeapDumper::do_load_class(klassOop k) { | |
1496 static u4 class_serial_num = 0; | |
1497 | |
1498 // len of HPROF_LOAD_CLASS record | |
1499 u4 remaining = 2*oopSize + 2*sizeof(u4); | |
1500 | |
1501 // write a HPROF_LOAD_CLASS for the class and each array class | |
1502 do { | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1503 DumperSupport::write_header(writer(), HPROF_LOAD_CLASS, remaining); |
0 | 1504 |
1505 // class serial number is just a number | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1506 writer()->write_u4(++class_serial_num); |
0 | 1507 |
1508 // class ID | |
1509 Klass* klass = Klass::cast(k); | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1510 writer()->write_classID(klass); |
0 | 1511 |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1512 // add the klassOop and class serial number pair |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1513 dumper()->add_class_serial_number(klass, class_serial_num); |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1514 |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1515 writer()->write_u4(STACK_TRACE_ID); |
0 | 1516 |
1517 // class name ID | |
1518 symbolOop name = klass->name(); | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1519 writer()->write_objectID(name); |
0 | 1520 |
1521 // write a LOAD_CLASS record for the array type (if it exists) | |
1522 k = klass->array_klass_or_null(); | |
1523 } while (k != NULL); | |
1524 } | |
1525 | |
1526 // writes a HPROF_GC_CLASS_DUMP record for the given class | |
1527 void VM_HeapDumper::do_class_dump(klassOop k) { | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1528 DumperSupport::dump_class_and_array_classes(writer(), k); |
0 | 1529 } |
1530 | |
1531 // writes a HPROF_GC_CLASS_DUMP records for a given basic type | |
1532 // array (and each multi-dimensional array too) | |
1533 void VM_HeapDumper::do_basic_type_array_class_dump(klassOop k) { | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1534 DumperSupport::dump_basic_type_array_class(writer(), k); |
0 | 1535 } |
1536 | |
1537 // Walk the stack of the given thread. | |
1538 // Dumps a HPROF_GC_ROOT_JAVA_FRAME record for each local | |
1539 // Dumps a HPROF_GC_ROOT_JNI_LOCAL record for each JNI local | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1540 // |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1541 // It returns the number of Java frames in this thread stack |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1542 int VM_HeapDumper::do_thread(JavaThread* java_thread, u4 thread_serial_num) { |
0 | 1543 JNILocalsDumper blk(writer(), thread_serial_num); |
1544 | |
1545 oop threadObj = java_thread->threadObj(); | |
1546 assert(threadObj != NULL, "sanity check"); | |
1547 | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1548 int stack_depth = 0; |
0 | 1549 if (java_thread->has_last_Java_frame()) { |
1550 | |
1551 // vframes are resource allocated | |
1552 Thread* current_thread = Thread::current(); | |
1553 ResourceMark rm(current_thread); | |
1554 HandleMark hm(current_thread); | |
1555 | |
1556 RegisterMap reg_map(java_thread); | |
1557 frame f = java_thread->last_frame(); | |
1558 vframe* vf = vframe::new_vframe(&f, ®_map, java_thread); | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1559 frame* last_entry_frame = NULL; |
0 | 1560 |
1561 while (vf != NULL) { | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1562 blk.set_frame_number(stack_depth); |
0 | 1563 if (vf->is_java_frame()) { |
1564 | |
1565 // java frame (interpreted, compiled, ...) | |
1566 javaVFrame *jvf = javaVFrame::cast(vf); | |
1567 if (!(jvf->method()->is_native())) { | |
1568 StackValueCollection* locals = jvf->locals(); | |
1569 for (int slot=0; slot<locals->size(); slot++) { | |
1570 if (locals->at(slot)->type() == T_OBJECT) { | |
1571 oop o = locals->obj_at(slot)(); | |
1572 | |
1573 if (o != NULL) { | |
1574 writer()->write_u1(HPROF_GC_ROOT_JAVA_FRAME); | |
1575 writer()->write_objectID(o); | |
1576 writer()->write_u4(thread_serial_num); | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1577 writer()->write_u4((u4) stack_depth); |
0 | 1578 } |
1579 } | |
1580 } | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1581 } else { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1582 // native frame |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1583 if (stack_depth == 0) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1584 // JNI locals for the top frame. |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1585 java_thread->active_handles()->oops_do(&blk); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1586 } else { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1587 if (last_entry_frame != NULL) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1588 // JNI locals for the entry frame |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1589 assert(last_entry_frame->is_entry_frame(), "checking"); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1590 last_entry_frame->entry_frame_call_wrapper()->handles()->oops_do(&blk); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1591 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1592 } |
0 | 1593 } |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1594 // increment only for Java frames |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1595 stack_depth++; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1596 last_entry_frame = NULL; |
0 | 1597 |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1598 } else { |
0 | 1599 // externalVFrame - if it's an entry frame then report any JNI locals |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1600 // as roots when we find the corresponding native javaVFrame |
0 | 1601 frame* fr = vf->frame_pointer(); |
1602 assert(fr != NULL, "sanity check"); | |
1603 if (fr->is_entry_frame()) { | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1604 last_entry_frame = fr; |
0 | 1605 } |
1606 } | |
1607 vf = vf->sender(); | |
1608 } | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1609 } else { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1610 // no last java frame but there may be JNI locals |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1611 java_thread->active_handles()->oops_do(&blk); |
0 | 1612 } |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1613 return stack_depth; |
0 | 1614 } |
1615 | |
1616 | |
1617 // write a HPROF_GC_ROOT_THREAD_OBJ record for each java thread. Then walk | |
1618 // the stack so that locals and JNI locals are dumped. | |
1619 void VM_HeapDumper::do_threads() { | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1620 for (int i=0; i < _num_threads; i++) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1621 JavaThread* thread = _stack_traces[i]->thread(); |
0 | 1622 oop threadObj = thread->threadObj(); |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1623 u4 thread_serial_num = i+1; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1624 u4 stack_serial_num = thread_serial_num + STACK_TRACE_ID; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1625 writer()->write_u1(HPROF_GC_ROOT_THREAD_OBJ); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1626 writer()->write_objectID(threadObj); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1627 writer()->write_u4(thread_serial_num); // thread number |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1628 writer()->write_u4(stack_serial_num); // stack trace serial number |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1629 int num_frames = do_thread(thread, thread_serial_num); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1630 assert(num_frames == _stack_traces[i]->get_stack_depth(), |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1631 "total number of Java frames not matched"); |
0 | 1632 } |
1633 } | |
1634 | |
1635 | |
1636 // The VM operation that dumps the heap. The dump consists of the following | |
1637 // records: | |
1638 // | |
1639 // HPROF_HEADER | |
1640 // [HPROF_UTF8]* | |
1641 // [HPROF_LOAD_CLASS]* | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1642 // [[HPROF_FRAME]*|HPROF_TRACE]* |
0 | 1643 // [HPROF_GC_CLASS_DUMP]* |
1644 // HPROF_HEAP_DUMP | |
1645 // | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1646 // The HPROF_TRACE records represent the stack traces where the heap dump |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1647 // is generated and a "dummy trace" record which does not include |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1648 // any frames. The dummy trace record is used to be referenced as the |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1649 // unknown object alloc site. |
0 | 1650 // |
1651 // The HPROF_HEAP_DUMP record has a length following by sub-records. To allow | |
1652 // the heap dump be generated in a single pass we remember the position of | |
1653 // the dump length and fix it up after all sub-records have been written. | |
1654 // To generate the sub-records we iterate over the heap, writing | |
1655 // HPROF_GC_INSTANCE_DUMP, HPROF_GC_OBJ_ARRAY_DUMP, and HPROF_GC_PRIM_ARRAY_DUMP | |
1656 // records as we go. Once that is done we write records for some of the GC | |
1657 // roots. | |
1658 | |
1659 void VM_HeapDumper::doit() { | |
1660 | |
1661 HandleMark hm; | |
1662 CollectedHeap* ch = Universe::heap(); | |
1663 if (_gc_before_heap_dump) { | |
1664 ch->collect_as_vm_thread(GCCause::_heap_dump); | |
1665 } else { | |
1666 // make the heap parsable (no need to retire TLABs) | |
1667 ch->ensure_parsability(false); | |
1668 } | |
1669 | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1670 // At this point we should be the only dumper active, so |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1671 // the following should be safe. |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1672 set_global_dumper(); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1673 set_global_writer(); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1674 |
0 | 1675 // Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
1676 size_t used = ch->used(); |
0 | 1677 const char* header; |
1678 if (used > (size_t)SegmentedHeapDumpThreshold) { | |
1679 set_segmented_dump(); | |
1680 header = "JAVA PROFILE 1.0.2"; | |
1681 } else { | |
1682 header = "JAVA PROFILE 1.0.1"; | |
1683 } | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1684 |
0 | 1685 // header is few bytes long - no chance to overflow int |
1686 writer()->write_raw((void*)header, (int)strlen(header)); | |
1687 writer()->write_u1(0); // terminator | |
1688 writer()->write_u4(oopSize); | |
1689 writer()->write_u8(os::javaTimeMillis()); | |
1690 | |
1691 // HPROF_UTF8 records | |
1692 SymbolTableDumper sym_dumper(writer()); | |
1693 SymbolTable::oops_do(&sym_dumper); | |
1694 | |
1695 // write HPROF_LOAD_CLASS records | |
1696 SystemDictionary::classes_do(&do_load_class); | |
1697 Universe::basic_type_classes_do(&do_load_class); | |
1698 | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1699 // write HPROF_FRAME and HPROF_TRACE records |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1700 // this must be called after _klass_map is built when iterating the classes above. |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1701 dump_stack_traces(); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1702 |
0 | 1703 // write HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT |
1704 write_dump_header(); | |
1705 | |
1706 // Writes HPROF_GC_CLASS_DUMP records | |
1707 SystemDictionary::classes_do(&do_class_dump); | |
1708 Universe::basic_type_classes_do(&do_basic_type_array_class_dump); | |
1709 check_segment_length(); | |
1710 | |
1711 // writes HPROF_GC_INSTANCE_DUMP records. | |
1712 // After each sub-record is written check_segment_length will be invoked. When | |
1713 // generated a segmented heap dump this allows us to check if the current | |
1714 // segment exceeds a threshold and if so, then a new segment is started. | |
1715 // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk | |
1716 // of the heap dump. | |
1717 HeapObjectDumper obj_dumper(this, writer()); | |
517
e9be0e04635a
6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents:
396
diff
changeset
|
1718 Universe::heap()->safe_object_iterate(&obj_dumper); |
0 | 1719 |
1720 // HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals | |
1721 do_threads(); | |
1722 check_segment_length(); | |
1723 | |
1724 // HPROF_GC_ROOT_MONITOR_USED | |
1725 MonitorUsedDumper mon_dumper(writer()); | |
1726 ObjectSynchronizer::oops_do(&mon_dumper); | |
1727 check_segment_length(); | |
1728 | |
1729 // HPROF_GC_ROOT_JNI_GLOBAL | |
1730 JNIGlobalsDumper jni_dumper(writer()); | |
1731 JNIHandles::oops_do(&jni_dumper); | |
1732 check_segment_length(); | |
1733 | |
1734 // HPROF_GC_ROOT_STICKY_CLASS | |
1735 StickyClassDumper class_dumper(writer()); | |
1736 SystemDictionary::always_strong_oops_do(&class_dumper); | |
1737 | |
1738 // fixes up the length of the dump record. In the case of a segmented | |
1739 // heap then the HPROF_HEAP_DUMP_END record is also written. | |
1740 end_of_dump(); | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1741 |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1742 // Now we clear the global variables, so that a future dumper might run. |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1743 clear_global_dumper(); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1744 clear_global_writer(); |
0 | 1745 } |
1746 | |
396
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1747 void VM_HeapDumper::dump_stack_traces() { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1748 // write a HPROF_TRACE record without any frames to be referenced as object alloc sites |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1749 DumperSupport::write_header(writer(), HPROF_TRACE, 3*sizeof(u4)); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1750 writer()->write_u4((u4) STACK_TRACE_ID); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1751 writer()->write_u4(0); // thread number |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1752 writer()->write_u4(0); // frame count |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1753 |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1754 _stack_traces = NEW_C_HEAP_ARRAY(ThreadStackTrace*, Threads::number_of_threads()); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1755 int frame_serial_num = 0; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1756 for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1757 oop threadObj = thread->threadObj(); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1758 if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1759 // dump thread stack trace |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1760 ThreadStackTrace* stack_trace = new ThreadStackTrace(thread, false); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1761 stack_trace->dump_stack_at_safepoint(-1); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1762 _stack_traces[_num_threads++] = stack_trace; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1763 |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1764 // write HPROF_FRAME records for this thread's stack trace |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1765 int depth = stack_trace->get_stack_depth(); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1766 int thread_frame_start = frame_serial_num; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1767 for (int j=0; j < depth; j++) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1768 StackFrameInfo* frame = stack_trace->stack_frame_at(j); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1769 methodOop m = frame->method(); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1770 int class_serial_num = _klass_map->find(Klass::cast(m->method_holder())); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1771 // the class serial number starts from 1 |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1772 assert(class_serial_num > 0, "class not found"); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1773 DumperSupport::dump_stack_frame(writer(), ++frame_serial_num, class_serial_num, m, frame->bci()); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1774 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1775 |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1776 // write HPROF_TRACE record for one thread |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1777 DumperSupport::write_header(writer(), HPROF_TRACE, 3*sizeof(u4) + depth*oopSize); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1778 int stack_serial_num = _num_threads + STACK_TRACE_ID; |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1779 writer()->write_u4(stack_serial_num); // stack trace serial number |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1780 writer()->write_u4((u4) _num_threads); // thread serial number |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1781 writer()->write_u4(depth); // frame count |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1782 for (int j=1; j <= depth; j++) { |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1783 writer()->write_id(thread_frame_start + j); |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1784 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1785 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1786 } |
4d05b7cb7842
6306922: Dump dump created by +HeapDumpOnOutOfMemoryError should include stack traces for stack roots
mchung
parents:
356
diff
changeset
|
1787 } |
0 | 1788 |
1789 // dump the heap to given path. | |
1790 int HeapDumper::dump(const char* path) { | |
1791 assert(path != NULL && strlen(path) > 0, "path missing"); | |
1792 | |
1793 // print message in interactive case | |
1794 if (print_to_tty()) { | |
1795 tty->print_cr("Dumping heap to %s ...", path); | |
1796 timer()->start(); | |
1797 } | |
1798 | |
1799 // create the dump writer. If the file can be opened then bail | |
1800 DumpWriter writer(path); | |
1801 if (!writer.is_open()) { | |
1802 set_error(writer.error()); | |
1803 if (print_to_tty()) { | |
1804 tty->print_cr("Unable to create %s: %s", path, | |
1805 (error() != NULL) ? error() : "reason unknown"); | |
1806 } | |
1807 return -1; | |
1808 } | |
1809 | |
1810 // generate the dump | |
1811 VM_HeapDumper dumper(&writer, _gc_before_heap_dump); | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1812 if (Thread::current()->is_VM_thread()) { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1813 assert(SafepointSynchronize::is_at_safepoint(), "Expected to be called at a safepoint"); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1814 dumper.doit(); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1815 } else { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1816 VMThread::execute(&dumper); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1817 } |
0 | 1818 |
1819 // close dump file and record any error that the writer may have encountered | |
1820 writer.close(); | |
1821 set_error(writer.error()); | |
1822 | |
1823 // print message in interactive case | |
1824 if (print_to_tty()) { | |
1825 timer()->stop(); | |
1826 if (error() == NULL) { | |
1827 char msg[256]; | |
1828 sprintf(msg, "Heap dump file created [%s bytes in %3.3f secs]", | |
1829 os::jlong_format_specifier(), timer()->seconds()); | |
1830 tty->print_cr(msg, writer.bytes_written()); | |
1831 } else { | |
1832 tty->print_cr("Dump file is incomplete: %s", writer.error()); | |
1833 } | |
1834 } | |
1835 | |
1836 return (writer.error() == NULL) ? 0 : -1; | |
1837 } | |
1838 | |
1839 // stop timer (if still active), and free any error string we might be holding | |
1840 HeapDumper::~HeapDumper() { | |
1841 if (timer()->is_active()) { | |
1842 timer()->stop(); | |
1843 } | |
1844 set_error(NULL); | |
1845 } | |
1846 | |
1847 | |
1848 // returns the error string (resource allocated), or NULL | |
1849 char* HeapDumper::error_as_C_string() const { | |
1850 if (error() != NULL) { | |
1851 char* str = NEW_RESOURCE_ARRAY(char, strlen(error())+1); | |
1852 strcpy(str, error()); | |
1853 return str; | |
1854 } else { | |
1855 return NULL; | |
1856 } | |
1857 } | |
1858 | |
1859 // set the error string | |
1860 void HeapDumper::set_error(char* error) { | |
1861 if (_error != NULL) { | |
1862 os::free(_error); | |
1863 } | |
1864 if (error == NULL) { | |
1865 _error = NULL; | |
1866 } else { | |
1867 _error = os::strdup(error); | |
1868 assert(_error != NULL, "allocation failure"); | |
1869 } | |
1870 } | |
1871 | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1872 // Called by error reporting by a single Java thread outside of a JVM safepoint, |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1873 // or by heap dumping by the VM thread during a (GC) safepoint. Thus, these various |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1874 // callers are strictly serialized and guaranteed not to interfere below. For more |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1875 // general use, however, this method will need modification to prevent |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1876 // inteference when updating the static variables base_path and dump_file_seq below. |
0 | 1877 void HeapDumper::dump_heap() { |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1878 static char base_path[JVM_MAXPATHLEN] = {'\0'}; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1879 static uint dump_file_seq = 0; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1880 char my_path[JVM_MAXPATHLEN] = {'\0'}; |
0 | 1881 |
1882 // The dump file defaults to java_pid<pid>.hprof in the current working | |
1883 // directory. HeapDumpPath=<file> can be used to specify an alternative | |
1884 // dump file name or a directory where dump file is created. | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1885 if (dump_file_seq == 0) { // first time in, we initialize base_path |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1886 bool use_default_filename = true; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1887 if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1888 // HeapDumpPath=<file> not specified |
0 | 1889 } else { |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1890 assert(strlen(HeapDumpPath) < sizeof(base_path), "HeapDumpPath too long"); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1891 strcpy(base_path, HeapDumpPath); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1892 // check if the path is a directory (must exist) |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1893 DIR* dir = os::opendir(base_path); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1894 if (dir == NULL) { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1895 use_default_filename = false; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1896 } else { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1897 // HeapDumpPath specified a directory. We append a file separator |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1898 // (if needed). |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1899 os::closedir(dir); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1900 size_t fs_len = strlen(os::file_separator()); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1901 if (strlen(base_path) >= fs_len) { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1902 char* end = base_path; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1903 end += (strlen(base_path) - fs_len); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1904 if (strcmp(end, os::file_separator()) != 0) { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1905 assert(strlen(base_path) + strlen(os::file_separator()) < sizeof(base_path), |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1906 "HeapDumpPath too long"); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1907 strcat(base_path, os::file_separator()); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1908 } |
0 | 1909 } |
1910 } | |
1911 } | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1912 // If HeapDumpPath wasn't a file name then we append the default name |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1913 if (use_default_filename) { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1914 char fn[32]; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1915 sprintf(fn, "java_pid%d", os::current_process_id()); |
1046 | 1916 assert(strlen(base_path) + strlen(fn) + strlen(".hprof") < sizeof(base_path), "HeapDumpPath too long"); |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1917 strcat(base_path, fn); |
1046 | 1918 strcat(base_path, ".hprof"); |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1919 } |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1920 assert(strlen(base_path) < sizeof(my_path), "Buffer too small"); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1921 strcpy(my_path, base_path); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1922 } else { |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1923 // Append a sequence number id for dumps following the first |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1924 char fn[33]; |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1925 sprintf(fn, ".%d", dump_file_seq); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1926 assert(strlen(base_path) + strlen(fn) < sizeof(my_path), "HeapDumpPath too long"); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1927 strcpy(my_path, base_path); |
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1928 strcat(my_path, fn); |
0 | 1929 } |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1930 dump_file_seq++; // increment seq number for next time we dump |
0 | 1931 |
1932 HeapDumper dumper(false /* no GC before heap dump */, | |
1933 true /* send to tty */); | |
615
c6c601a0f2d6
6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents:
517
diff
changeset
|
1934 dumper.dump(my_path); |
0 | 1935 } |