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