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