1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/services/heapDumper.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,2011 @@ 1.4 +/* 1.5 + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "classfile/symbolTable.hpp" 1.30 +#include "classfile/systemDictionary.hpp" 1.31 +#include "classfile/vmSymbols.hpp" 1.32 +#include "gc_implementation/shared/vmGCOperations.hpp" 1.33 +#include "memory/gcLocker.inline.hpp" 1.34 +#include "memory/genCollectedHeap.hpp" 1.35 +#include "memory/universe.hpp" 1.36 +#include "oops/objArrayKlass.hpp" 1.37 +#include "runtime/javaCalls.hpp" 1.38 +#include "runtime/jniHandles.hpp" 1.39 +#include "runtime/reflectionUtils.hpp" 1.40 +#include "runtime/vframe.hpp" 1.41 +#include "runtime/vmThread.hpp" 1.42 +#include "runtime/vm_operations.hpp" 1.43 +#include "services/heapDumper.hpp" 1.44 +#include "services/threadService.hpp" 1.45 +#include "utilities/ostream.hpp" 1.46 +#include "utilities/macros.hpp" 1.47 +#if INCLUDE_ALL_GCS 1.48 +#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" 1.49 +#endif // INCLUDE_ALL_GCS 1.50 + 1.51 +/* 1.52 + * HPROF binary format - description copied from: 1.53 + * src/share/demo/jvmti/hprof/hprof_io.c 1.54 + * 1.55 + * 1.56 + * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" 1.57 + * (0-terminated) 1.58 + * 1.59 + * u4 size of identifiers. Identifiers are used to represent 1.60 + * UTF8 strings, objects, stack traces, etc. They usually 1.61 + * have the same size as host pointers. For example, on 1.62 + * Solaris and Win32, the size is 4. 1.63 + * u4 high word 1.64 + * u4 low word number of milliseconds since 0:00 GMT, 1/1/70 1.65 + * [record]* a sequence of records. 1.66 + * 1.67 + * 1.68 + * Record format: 1.69 + * 1.70 + * u1 a TAG denoting the type of the record 1.71 + * u4 number of *microseconds* since the time stamp in the 1.72 + * header. (wraps around in a little more than an hour) 1.73 + * u4 number of bytes *remaining* in the record. Note that 1.74 + * this number excludes the tag and the length field itself. 1.75 + * [u1]* BODY of the record (a sequence of bytes) 1.76 + * 1.77 + * 1.78 + * The following TAGs are supported: 1.79 + * 1.80 + * TAG BODY notes 1.81 + *---------------------------------------------------------- 1.82 + * HPROF_UTF8 a UTF8-encoded name 1.83 + * 1.84 + * id name ID 1.85 + * [u1]* UTF8 characters (no trailing zero) 1.86 + * 1.87 + * HPROF_LOAD_CLASS a newly loaded class 1.88 + * 1.89 + * u4 class serial number (> 0) 1.90 + * id class object ID 1.91 + * u4 stack trace serial number 1.92 + * id class name ID 1.93 + * 1.94 + * HPROF_UNLOAD_CLASS an unloading class 1.95 + * 1.96 + * u4 class serial_number 1.97 + * 1.98 + * HPROF_FRAME a Java stack frame 1.99 + * 1.100 + * id stack frame ID 1.101 + * id method name ID 1.102 + * id method signature ID 1.103 + * id source file name ID 1.104 + * u4 class serial number 1.105 + * i4 line number. >0: normal 1.106 + * -1: unknown 1.107 + * -2: compiled method 1.108 + * -3: native method 1.109 + * 1.110 + * HPROF_TRACE a Java stack trace 1.111 + * 1.112 + * u4 stack trace serial number 1.113 + * u4 thread serial number 1.114 + * u4 number of frames 1.115 + * [id]* stack frame IDs 1.116 + * 1.117 + * 1.118 + * HPROF_ALLOC_SITES a set of heap allocation sites, obtained after GC 1.119 + * 1.120 + * u2 flags 0x0001: incremental vs. complete 1.121 + * 0x0002: sorted by allocation vs. live 1.122 + * 0x0004: whether to force a GC 1.123 + * u4 cutoff ratio 1.124 + * u4 total live bytes 1.125 + * u4 total live instances 1.126 + * u8 total bytes allocated 1.127 + * u8 total instances allocated 1.128 + * u4 number of sites that follow 1.129 + * [u1 is_array: 0: normal object 1.130 + * 2: object array 1.131 + * 4: boolean array 1.132 + * 5: char array 1.133 + * 6: float array 1.134 + * 7: double array 1.135 + * 8: byte array 1.136 + * 9: short array 1.137 + * 10: int array 1.138 + * 11: long array 1.139 + * u4 class serial number (may be zero during startup) 1.140 + * u4 stack trace serial number 1.141 + * u4 number of bytes alive 1.142 + * u4 number of instances alive 1.143 + * u4 number of bytes allocated 1.144 + * u4]* number of instance allocated 1.145 + * 1.146 + * HPROF_START_THREAD a newly started thread. 1.147 + * 1.148 + * u4 thread serial number (> 0) 1.149 + * id thread object ID 1.150 + * u4 stack trace serial number 1.151 + * id thread name ID 1.152 + * id thread group name ID 1.153 + * id thread group parent name ID 1.154 + * 1.155 + * HPROF_END_THREAD a terminating thread. 1.156 + * 1.157 + * u4 thread serial number 1.158 + * 1.159 + * HPROF_HEAP_SUMMARY heap summary 1.160 + * 1.161 + * u4 total live bytes 1.162 + * u4 total live instances 1.163 + * u8 total bytes allocated 1.164 + * u8 total instances allocated 1.165 + * 1.166 + * HPROF_HEAP_DUMP denote a heap dump 1.167 + * 1.168 + * [heap dump sub-records]* 1.169 + * 1.170 + * There are four kinds of heap dump sub-records: 1.171 + * 1.172 + * u1 sub-record type 1.173 + * 1.174 + * HPROF_GC_ROOT_UNKNOWN unknown root 1.175 + * 1.176 + * id object ID 1.177 + * 1.178 + * HPROF_GC_ROOT_THREAD_OBJ thread object 1.179 + * 1.180 + * id thread object ID (may be 0 for a 1.181 + * thread newly attached through JNI) 1.182 + * u4 thread sequence number 1.183 + * u4 stack trace sequence number 1.184 + * 1.185 + * HPROF_GC_ROOT_JNI_GLOBAL JNI global ref root 1.186 + * 1.187 + * id object ID 1.188 + * id JNI global ref ID 1.189 + * 1.190 + * HPROF_GC_ROOT_JNI_LOCAL JNI local ref 1.191 + * 1.192 + * id object ID 1.193 + * u4 thread serial number 1.194 + * u4 frame # in stack trace (-1 for empty) 1.195 + * 1.196 + * HPROF_GC_ROOT_JAVA_FRAME Java stack frame 1.197 + * 1.198 + * id object ID 1.199 + * u4 thread serial number 1.200 + * u4 frame # in stack trace (-1 for empty) 1.201 + * 1.202 + * HPROF_GC_ROOT_NATIVE_STACK Native stack 1.203 + * 1.204 + * id object ID 1.205 + * u4 thread serial number 1.206 + * 1.207 + * HPROF_GC_ROOT_STICKY_CLASS System class 1.208 + * 1.209 + * id object ID 1.210 + * 1.211 + * HPROF_GC_ROOT_THREAD_BLOCK Reference from thread block 1.212 + * 1.213 + * id object ID 1.214 + * u4 thread serial number 1.215 + * 1.216 + * HPROF_GC_ROOT_MONITOR_USED Busy monitor 1.217 + * 1.218 + * id object ID 1.219 + * 1.220 + * HPROF_GC_CLASS_DUMP dump of a class object 1.221 + * 1.222 + * id class object ID 1.223 + * u4 stack trace serial number 1.224 + * id super class object ID 1.225 + * id class loader object ID 1.226 + * id signers object ID 1.227 + * id protection domain object ID 1.228 + * id reserved 1.229 + * id reserved 1.230 + * 1.231 + * u4 instance size (in bytes) 1.232 + * 1.233 + * u2 size of constant pool 1.234 + * [u2, constant pool index, 1.235 + * ty, type 1.236 + * 2: object 1.237 + * 4: boolean 1.238 + * 5: char 1.239 + * 6: float 1.240 + * 7: double 1.241 + * 8: byte 1.242 + * 9: short 1.243 + * 10: int 1.244 + * 11: long 1.245 + * vl]* and value 1.246 + * 1.247 + * u2 number of static fields 1.248 + * [id, static field name, 1.249 + * ty, type, 1.250 + * vl]* and value 1.251 + * 1.252 + * u2 number of inst. fields (not inc. super) 1.253 + * [id, instance field name, 1.254 + * ty]* type 1.255 + * 1.256 + * HPROF_GC_INSTANCE_DUMP dump of a normal object 1.257 + * 1.258 + * id object ID 1.259 + * u4 stack trace serial number 1.260 + * id class object ID 1.261 + * u4 number of bytes that follow 1.262 + * [vl]* instance field values (class, followed 1.263 + * by super, super's super ...) 1.264 + * 1.265 + * HPROF_GC_OBJ_ARRAY_DUMP dump of an object array 1.266 + * 1.267 + * id array object ID 1.268 + * u4 stack trace serial number 1.269 + * u4 number of elements 1.270 + * id array class ID 1.271 + * [id]* elements 1.272 + * 1.273 + * HPROF_GC_PRIM_ARRAY_DUMP dump of a primitive array 1.274 + * 1.275 + * id array object ID 1.276 + * u4 stack trace serial number 1.277 + * u4 number of elements 1.278 + * u1 element type 1.279 + * 4: boolean array 1.280 + * 5: char array 1.281 + * 6: float array 1.282 + * 7: double array 1.283 + * 8: byte array 1.284 + * 9: short array 1.285 + * 10: int array 1.286 + * 11: long array 1.287 + * [u1]* elements 1.288 + * 1.289 + * HPROF_CPU_SAMPLES a set of sample traces of running threads 1.290 + * 1.291 + * u4 total number of samples 1.292 + * u4 # of traces 1.293 + * [u4 # of samples 1.294 + * u4]* stack trace serial number 1.295 + * 1.296 + * HPROF_CONTROL_SETTINGS the settings of on/off switches 1.297 + * 1.298 + * u4 0x00000001: alloc traces on/off 1.299 + * 0x00000002: cpu sampling on/off 1.300 + * u2 stack trace depth 1.301 + * 1.302 + * 1.303 + * When the header is "JAVA PROFILE 1.0.2" a heap dump can optionally 1.304 + * be generated as a sequence of heap dump segments. This sequence is 1.305 + * terminated by an end record. The additional tags allowed by format 1.306 + * "JAVA PROFILE 1.0.2" are: 1.307 + * 1.308 + * HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment 1.309 + * 1.310 + * [heap dump sub-records]* 1.311 + * The same sub-record types allowed by HPROF_HEAP_DUMP 1.312 + * 1.313 + * HPROF_HEAP_DUMP_END denotes the end of a heap dump 1.314 + * 1.315 + */ 1.316 + 1.317 + 1.318 +// HPROF tags 1.319 + 1.320 +typedef enum { 1.321 + // top-level records 1.322 + HPROF_UTF8 = 0x01, 1.323 + HPROF_LOAD_CLASS = 0x02, 1.324 + HPROF_UNLOAD_CLASS = 0x03, 1.325 + HPROF_FRAME = 0x04, 1.326 + HPROF_TRACE = 0x05, 1.327 + HPROF_ALLOC_SITES = 0x06, 1.328 + HPROF_HEAP_SUMMARY = 0x07, 1.329 + HPROF_START_THREAD = 0x0A, 1.330 + HPROF_END_THREAD = 0x0B, 1.331 + HPROF_HEAP_DUMP = 0x0C, 1.332 + HPROF_CPU_SAMPLES = 0x0D, 1.333 + HPROF_CONTROL_SETTINGS = 0x0E, 1.334 + 1.335 + // 1.0.2 record types 1.336 + HPROF_HEAP_DUMP_SEGMENT = 0x1C, 1.337 + HPROF_HEAP_DUMP_END = 0x2C, 1.338 + 1.339 + // field types 1.340 + HPROF_ARRAY_OBJECT = 0x01, 1.341 + HPROF_NORMAL_OBJECT = 0x02, 1.342 + HPROF_BOOLEAN = 0x04, 1.343 + HPROF_CHAR = 0x05, 1.344 + HPROF_FLOAT = 0x06, 1.345 + HPROF_DOUBLE = 0x07, 1.346 + HPROF_BYTE = 0x08, 1.347 + HPROF_SHORT = 0x09, 1.348 + HPROF_INT = 0x0A, 1.349 + HPROF_LONG = 0x0B, 1.350 + 1.351 + // data-dump sub-records 1.352 + HPROF_GC_ROOT_UNKNOWN = 0xFF, 1.353 + HPROF_GC_ROOT_JNI_GLOBAL = 0x01, 1.354 + HPROF_GC_ROOT_JNI_LOCAL = 0x02, 1.355 + HPROF_GC_ROOT_JAVA_FRAME = 0x03, 1.356 + HPROF_GC_ROOT_NATIVE_STACK = 0x04, 1.357 + HPROF_GC_ROOT_STICKY_CLASS = 0x05, 1.358 + HPROF_GC_ROOT_THREAD_BLOCK = 0x06, 1.359 + HPROF_GC_ROOT_MONITOR_USED = 0x07, 1.360 + HPROF_GC_ROOT_THREAD_OBJ = 0x08, 1.361 + HPROF_GC_CLASS_DUMP = 0x20, 1.362 + HPROF_GC_INSTANCE_DUMP = 0x21, 1.363 + HPROF_GC_OBJ_ARRAY_DUMP = 0x22, 1.364 + HPROF_GC_PRIM_ARRAY_DUMP = 0x23 1.365 +} hprofTag; 1.366 + 1.367 +// Default stack trace ID (used for dummy HPROF_TRACE record) 1.368 +enum { 1.369 + STACK_TRACE_ID = 1, 1.370 + INITIAL_CLASS_COUNT = 200 1.371 +}; 1.372 + 1.373 +// Supports I/O operations on a dump file 1.374 + 1.375 +class DumpWriter : public StackObj { 1.376 + private: 1.377 + enum { 1.378 + io_buffer_size = 8*M 1.379 + }; 1.380 + 1.381 + int _fd; // file descriptor (-1 if dump file not open) 1.382 + jlong _bytes_written; // number of byte written to dump file 1.383 + 1.384 + char* _buffer; // internal buffer 1.385 + int _size; 1.386 + int _pos; 1.387 + 1.388 + char* _error; // error message when I/O fails 1.389 + 1.390 + void set_file_descriptor(int fd) { _fd = fd; } 1.391 + int file_descriptor() const { return _fd; } 1.392 + 1.393 + char* buffer() const { return _buffer; } 1.394 + int buffer_size() const { return _size; } 1.395 + int position() const { return _pos; } 1.396 + void set_position(int pos) { _pos = pos; } 1.397 + 1.398 + void set_error(const char* error) { _error = (char*)os::strdup(error); } 1.399 + 1.400 + // all I/O go through this function 1.401 + void write_internal(void* s, int len); 1.402 + 1.403 + public: 1.404 + DumpWriter(const char* path); 1.405 + ~DumpWriter(); 1.406 + 1.407 + void close(); 1.408 + bool is_open() const { return file_descriptor() >= 0; } 1.409 + void flush(); 1.410 + 1.411 + // total number of bytes written to the disk 1.412 + jlong bytes_written() const { return _bytes_written; } 1.413 + 1.414 + // adjust the number of bytes written to disk (used to keep the count 1.415 + // of the number of bytes written in case of rewrites) 1.416 + void adjust_bytes_written(jlong n) { _bytes_written += n; } 1.417 + 1.418 + // number of (buffered) bytes as yet unwritten to the dump file 1.419 + jlong bytes_unwritten() const { return (jlong)position(); } 1.420 + 1.421 + char* error() const { return _error; } 1.422 + 1.423 + jlong current_offset(); 1.424 + void seek_to_offset(jlong pos); 1.425 + 1.426 + // writer functions 1.427 + void write_raw(void* s, int len); 1.428 + void write_u1(u1 x) { write_raw((void*)&x, 1); } 1.429 + void write_u2(u2 x); 1.430 + void write_u4(u4 x); 1.431 + void write_u8(u8 x); 1.432 + void write_objectID(oop o); 1.433 + void write_symbolID(Symbol* o); 1.434 + void write_classID(Klass* k); 1.435 + void write_id(u4 x); 1.436 +}; 1.437 + 1.438 +DumpWriter::DumpWriter(const char* path) { 1.439 + // try to allocate an I/O buffer of io_buffer_size. If there isn't 1.440 + // sufficient memory then reduce size until we can allocate something. 1.441 + _size = io_buffer_size; 1.442 + do { 1.443 + _buffer = (char*)os::malloc(_size, mtInternal); 1.444 + if (_buffer == NULL) { 1.445 + _size = _size >> 1; 1.446 + } 1.447 + } while (_buffer == NULL && _size > 0); 1.448 + assert((_size > 0 && _buffer != NULL) || (_size == 0 && _buffer == NULL), "sanity check"); 1.449 + _pos = 0; 1.450 + _error = NULL; 1.451 + _bytes_written = 0L; 1.452 + _fd = os::create_binary_file(path, false); // don't replace existing file 1.453 + 1.454 + // if the open failed we record the error 1.455 + if (_fd < 0) { 1.456 + _error = (char*)os::strdup(strerror(errno)); 1.457 + } 1.458 +} 1.459 + 1.460 +DumpWriter::~DumpWriter() { 1.461 + // flush and close dump file 1.462 + if (is_open()) { 1.463 + close(); 1.464 + } 1.465 + if (_buffer != NULL) os::free(_buffer); 1.466 + if (_error != NULL) os::free(_error); 1.467 +} 1.468 + 1.469 +// closes dump file (if open) 1.470 +void DumpWriter::close() { 1.471 + // flush and close dump file 1.472 + if (is_open()) { 1.473 + flush(); 1.474 + ::close(file_descriptor()); 1.475 + set_file_descriptor(-1); 1.476 + } 1.477 +} 1.478 + 1.479 +// write directly to the file 1.480 +void DumpWriter::write_internal(void* s, int len) { 1.481 + if (is_open()) { 1.482 + int n = ::write(file_descriptor(), s, len); 1.483 + if (n > 0) { 1.484 + _bytes_written += n; 1.485 + } 1.486 + if (n != len) { 1.487 + if (n < 0) { 1.488 + set_error(strerror(errno)); 1.489 + } else { 1.490 + set_error("file size limit"); 1.491 + } 1.492 + ::close(file_descriptor()); 1.493 + set_file_descriptor(-1); 1.494 + } 1.495 + } 1.496 +} 1.497 + 1.498 +// write raw bytes 1.499 +void DumpWriter::write_raw(void* s, int len) { 1.500 + if (is_open()) { 1.501 + // flush buffer to make toom 1.502 + if ((position()+ len) >= buffer_size()) { 1.503 + flush(); 1.504 + } 1.505 + 1.506 + // buffer not available or too big to buffer it 1.507 + if ((buffer() == NULL) || (len >= buffer_size())) { 1.508 + write_internal(s, len); 1.509 + } else { 1.510 + // Should optimize this for u1/u2/u4/u8 sizes. 1.511 + memcpy(buffer() + position(), s, len); 1.512 + set_position(position() + len); 1.513 + } 1.514 + } 1.515 +} 1.516 + 1.517 +// flush any buffered bytes to the file 1.518 +void DumpWriter::flush() { 1.519 + if (is_open() && position() > 0) { 1.520 + write_internal(buffer(), position()); 1.521 + set_position(0); 1.522 + } 1.523 +} 1.524 + 1.525 + 1.526 +jlong DumpWriter::current_offset() { 1.527 + if (is_open()) { 1.528 + // the offset is the file offset plus whatever we have buffered 1.529 + jlong offset = os::current_file_offset(file_descriptor()); 1.530 + assert(offset >= 0, "lseek failed"); 1.531 + return offset + (jlong)position(); 1.532 + } else { 1.533 + return (jlong)-1; 1.534 + } 1.535 +} 1.536 + 1.537 +void DumpWriter::seek_to_offset(jlong off) { 1.538 + assert(off >= 0, "bad offset"); 1.539 + 1.540 + // need to flush before seeking 1.541 + flush(); 1.542 + 1.543 + // may be closed due to I/O error 1.544 + if (is_open()) { 1.545 + jlong n = os::seek_to_file_offset(file_descriptor(), off); 1.546 + assert(n >= 0, "lseek failed"); 1.547 + } 1.548 +} 1.549 + 1.550 +void DumpWriter::write_u2(u2 x) { 1.551 + u2 v; 1.552 + Bytes::put_Java_u2((address)&v, x); 1.553 + write_raw((void*)&v, 2); 1.554 +} 1.555 + 1.556 +void DumpWriter::write_u4(u4 x) { 1.557 + u4 v; 1.558 + Bytes::put_Java_u4((address)&v, x); 1.559 + write_raw((void*)&v, 4); 1.560 +} 1.561 + 1.562 +void DumpWriter::write_u8(u8 x) { 1.563 + u8 v; 1.564 + Bytes::put_Java_u8((address)&v, x); 1.565 + write_raw((void*)&v, 8); 1.566 +} 1.567 + 1.568 +void DumpWriter::write_objectID(oop o) { 1.569 + address a = (address)o; 1.570 +#ifdef _LP64 1.571 + write_u8((u8)a); 1.572 +#else 1.573 + write_u4((u4)a); 1.574 +#endif 1.575 +} 1.576 + 1.577 +void DumpWriter::write_symbolID(Symbol* s) { 1.578 + address a = (address)((uintptr_t)s); 1.579 +#ifdef _LP64 1.580 + write_u8((u8)a); 1.581 +#else 1.582 + write_u4((u4)a); 1.583 +#endif 1.584 +} 1.585 + 1.586 +void DumpWriter::write_id(u4 x) { 1.587 +#ifdef _LP64 1.588 + write_u8((u8) x); 1.589 +#else 1.590 + write_u4(x); 1.591 +#endif 1.592 +} 1.593 + 1.594 +// We use java mirror as the class ID 1.595 +void DumpWriter::write_classID(Klass* k) { 1.596 + write_objectID(k->java_mirror()); 1.597 +} 1.598 + 1.599 + 1.600 + 1.601 +// Support class with a collection of functions used when dumping the heap 1.602 + 1.603 +class DumperSupport : AllStatic { 1.604 + public: 1.605 + 1.606 + // write a header of the given type 1.607 + static void write_header(DumpWriter* writer, hprofTag tag, u4 len); 1.608 + 1.609 + // returns hprof tag for the given type signature 1.610 + static hprofTag sig2tag(Symbol* sig); 1.611 + // returns hprof tag for the given basic type 1.612 + static hprofTag type2tag(BasicType type); 1.613 + 1.614 + // returns the size of the instance of the given class 1.615 + static u4 instance_size(Klass* k); 1.616 + 1.617 + // dump a jfloat 1.618 + static void dump_float(DumpWriter* writer, jfloat f); 1.619 + // dump a jdouble 1.620 + static void dump_double(DumpWriter* writer, jdouble d); 1.621 + // dumps the raw value of the given field 1.622 + static void dump_field_value(DumpWriter* writer, char type, address addr); 1.623 + // dumps static fields of the given class 1.624 + static void dump_static_fields(DumpWriter* writer, Klass* k); 1.625 + // dump the raw values of the instance fields of the given object 1.626 + static void dump_instance_fields(DumpWriter* writer, oop o); 1.627 + // dumps the definition of the instance fields for a given class 1.628 + static void dump_instance_field_descriptors(DumpWriter* writer, Klass* k); 1.629 + // creates HPROF_GC_INSTANCE_DUMP record for the given object 1.630 + static void dump_instance(DumpWriter* writer, oop o); 1.631 + // creates HPROF_GC_CLASS_DUMP record for the given class and each of its 1.632 + // array classes 1.633 + static void dump_class_and_array_classes(DumpWriter* writer, Klass* k); 1.634 + // creates HPROF_GC_CLASS_DUMP record for a given primitive array 1.635 + // class (and each multi-dimensional array class too) 1.636 + static void dump_basic_type_array_class(DumpWriter* writer, Klass* k); 1.637 + 1.638 + // creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array 1.639 + static void dump_object_array(DumpWriter* writer, objArrayOop array); 1.640 + // creates HPROF_GC_PRIM_ARRAY_DUMP record for the given type array 1.641 + static void dump_prim_array(DumpWriter* writer, typeArrayOop array); 1.642 + // create HPROF_FRAME record for the given method and bci 1.643 + static void dump_stack_frame(DumpWriter* writer, int frame_serial_num, int class_serial_num, Method* m, int bci); 1.644 +}; 1.645 + 1.646 +// write a header of the given type 1.647 +void DumperSupport:: write_header(DumpWriter* writer, hprofTag tag, u4 len) { 1.648 + writer->write_u1((u1)tag); 1.649 + writer->write_u4(0); // current ticks 1.650 + writer->write_u4(len); 1.651 +} 1.652 + 1.653 +// returns hprof tag for the given type signature 1.654 +hprofTag DumperSupport::sig2tag(Symbol* sig) { 1.655 + switch (sig->byte_at(0)) { 1.656 + case JVM_SIGNATURE_CLASS : return HPROF_NORMAL_OBJECT; 1.657 + case JVM_SIGNATURE_ARRAY : return HPROF_NORMAL_OBJECT; 1.658 + case JVM_SIGNATURE_BYTE : return HPROF_BYTE; 1.659 + case JVM_SIGNATURE_CHAR : return HPROF_CHAR; 1.660 + case JVM_SIGNATURE_FLOAT : return HPROF_FLOAT; 1.661 + case JVM_SIGNATURE_DOUBLE : return HPROF_DOUBLE; 1.662 + case JVM_SIGNATURE_INT : return HPROF_INT; 1.663 + case JVM_SIGNATURE_LONG : return HPROF_LONG; 1.664 + case JVM_SIGNATURE_SHORT : return HPROF_SHORT; 1.665 + case JVM_SIGNATURE_BOOLEAN : return HPROF_BOOLEAN; 1.666 + default : ShouldNotReachHere(); /* to shut up compiler */ return HPROF_BYTE; 1.667 + } 1.668 +} 1.669 + 1.670 +hprofTag DumperSupport::type2tag(BasicType type) { 1.671 + switch (type) { 1.672 + case T_BYTE : return HPROF_BYTE; 1.673 + case T_CHAR : return HPROF_CHAR; 1.674 + case T_FLOAT : return HPROF_FLOAT; 1.675 + case T_DOUBLE : return HPROF_DOUBLE; 1.676 + case T_INT : return HPROF_INT; 1.677 + case T_LONG : return HPROF_LONG; 1.678 + case T_SHORT : return HPROF_SHORT; 1.679 + case T_BOOLEAN : return HPROF_BOOLEAN; 1.680 + default : ShouldNotReachHere(); /* to shut up compiler */ return HPROF_BYTE; 1.681 + } 1.682 +} 1.683 + 1.684 +// dump a jfloat 1.685 +void DumperSupport::dump_float(DumpWriter* writer, jfloat f) { 1.686 + if (g_isnan(f)) { 1.687 + writer->write_u4(0x7fc00000); // collapsing NaNs 1.688 + } else { 1.689 + union { 1.690 + int i; 1.691 + float f; 1.692 + } u; 1.693 + u.f = (float)f; 1.694 + writer->write_u4((u4)u.i); 1.695 + } 1.696 +} 1.697 + 1.698 +// dump a jdouble 1.699 +void DumperSupport::dump_double(DumpWriter* writer, jdouble d) { 1.700 + union { 1.701 + jlong l; 1.702 + double d; 1.703 + } u; 1.704 + if (g_isnan(d)) { // collapsing NaNs 1.705 + u.l = (jlong)(0x7ff80000); 1.706 + u.l = (u.l << 32); 1.707 + } else { 1.708 + u.d = (double)d; 1.709 + } 1.710 + writer->write_u8((u8)u.l); 1.711 +} 1.712 + 1.713 +// dumps the raw value of the given field 1.714 +void DumperSupport::dump_field_value(DumpWriter* writer, char type, address addr) { 1.715 + switch (type) { 1.716 + case JVM_SIGNATURE_CLASS : 1.717 + case JVM_SIGNATURE_ARRAY : { 1.718 + oop o; 1.719 + if (UseCompressedOops) { 1.720 + o = oopDesc::load_decode_heap_oop((narrowOop*)addr); 1.721 + } else { 1.722 + o = oopDesc::load_decode_heap_oop((oop*)addr); 1.723 + } 1.724 + 1.725 + // reflection and sun.misc.Unsafe classes may have a reference to a 1.726 + // Klass* so filter it out. 1.727 + assert(o->is_oop_or_null(), "should always be an oop"); 1.728 + writer->write_objectID(o); 1.729 + break; 1.730 + } 1.731 + case JVM_SIGNATURE_BYTE : { 1.732 + jbyte* b = (jbyte*)addr; 1.733 + writer->write_u1((u1)*b); 1.734 + break; 1.735 + } 1.736 + case JVM_SIGNATURE_CHAR : { 1.737 + jchar* c = (jchar*)addr; 1.738 + writer->write_u2((u2)*c); 1.739 + break; 1.740 + } 1.741 + case JVM_SIGNATURE_SHORT : { 1.742 + jshort* s = (jshort*)addr; 1.743 + writer->write_u2((u2)*s); 1.744 + break; 1.745 + } 1.746 + case JVM_SIGNATURE_FLOAT : { 1.747 + jfloat* f = (jfloat*)addr; 1.748 + dump_float(writer, *f); 1.749 + break; 1.750 + } 1.751 + case JVM_SIGNATURE_DOUBLE : { 1.752 + jdouble* f = (jdouble*)addr; 1.753 + dump_double(writer, *f); 1.754 + break; 1.755 + } 1.756 + case JVM_SIGNATURE_INT : { 1.757 + jint* i = (jint*)addr; 1.758 + writer->write_u4((u4)*i); 1.759 + break; 1.760 + } 1.761 + case JVM_SIGNATURE_LONG : { 1.762 + jlong* l = (jlong*)addr; 1.763 + writer->write_u8((u8)*l); 1.764 + break; 1.765 + } 1.766 + case JVM_SIGNATURE_BOOLEAN : { 1.767 + jboolean* b = (jboolean*)addr; 1.768 + writer->write_u1((u1)*b); 1.769 + break; 1.770 + } 1.771 + default : ShouldNotReachHere(); 1.772 + } 1.773 +} 1.774 + 1.775 +// returns the size of the instance of the given class 1.776 +u4 DumperSupport::instance_size(Klass* k) { 1.777 + HandleMark hm; 1.778 + instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); 1.779 + 1.780 + int size = 0; 1.781 + 1.782 + for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { 1.783 + if (!fld.access_flags().is_static()) { 1.784 + Symbol* sig = fld.signature(); 1.785 + switch (sig->byte_at(0)) { 1.786 + case JVM_SIGNATURE_CLASS : 1.787 + case JVM_SIGNATURE_ARRAY : size += oopSize; break; 1.788 + 1.789 + case JVM_SIGNATURE_BYTE : 1.790 + case JVM_SIGNATURE_BOOLEAN : size += 1; break; 1.791 + 1.792 + case JVM_SIGNATURE_CHAR : 1.793 + case JVM_SIGNATURE_SHORT : size += 2; break; 1.794 + 1.795 + case JVM_SIGNATURE_INT : 1.796 + case JVM_SIGNATURE_FLOAT : size += 4; break; 1.797 + 1.798 + case JVM_SIGNATURE_LONG : 1.799 + case JVM_SIGNATURE_DOUBLE : size += 8; break; 1.800 + 1.801 + default : ShouldNotReachHere(); 1.802 + } 1.803 + } 1.804 + } 1.805 + return (u4)size; 1.806 +} 1.807 + 1.808 +// dumps static fields of the given class 1.809 +void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { 1.810 + HandleMark hm; 1.811 + instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); 1.812 + 1.813 + // pass 1 - count the static fields 1.814 + u2 field_count = 0; 1.815 + for (FieldStream fldc(ikh, true, true); !fldc.eos(); fldc.next()) { 1.816 + if (fldc.access_flags().is_static()) field_count++; 1.817 + } 1.818 + 1.819 + writer->write_u2(field_count); 1.820 + 1.821 + // pass 2 - dump the field descriptors and raw values 1.822 + for (FieldStream fld(ikh, true, true); !fld.eos(); fld.next()) { 1.823 + if (fld.access_flags().is_static()) { 1.824 + Symbol* sig = fld.signature(); 1.825 + 1.826 + writer->write_symbolID(fld.name()); // name 1.827 + writer->write_u1(sig2tag(sig)); // type 1.828 + 1.829 + // value 1.830 + int offset = fld.offset(); 1.831 + address addr = (address)ikh->java_mirror() + offset; 1.832 + 1.833 + dump_field_value(writer, sig->byte_at(0), addr); 1.834 + } 1.835 + } 1.836 +} 1.837 + 1.838 +// dump the raw values of the instance fields of the given object 1.839 +void DumperSupport::dump_instance_fields(DumpWriter* writer, oop o) { 1.840 + HandleMark hm; 1.841 + instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), o->klass()); 1.842 + 1.843 + for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { 1.844 + if (!fld.access_flags().is_static()) { 1.845 + Symbol* sig = fld.signature(); 1.846 + address addr = (address)o + fld.offset(); 1.847 + 1.848 + dump_field_value(writer, sig->byte_at(0), addr); 1.849 + } 1.850 + } 1.851 +} 1.852 + 1.853 +// dumps the definition of the instance fields for a given class 1.854 +void DumperSupport::dump_instance_field_descriptors(DumpWriter* writer, Klass* k) { 1.855 + HandleMark hm; 1.856 + instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); 1.857 + 1.858 + // pass 1 - count the instance fields 1.859 + u2 field_count = 0; 1.860 + for (FieldStream fldc(ikh, true, true); !fldc.eos(); fldc.next()) { 1.861 + if (!fldc.access_flags().is_static()) field_count++; 1.862 + } 1.863 + 1.864 + writer->write_u2(field_count); 1.865 + 1.866 + // pass 2 - dump the field descriptors 1.867 + for (FieldStream fld(ikh, true, true); !fld.eos(); fld.next()) { 1.868 + if (!fld.access_flags().is_static()) { 1.869 + Symbol* sig = fld.signature(); 1.870 + 1.871 + writer->write_symbolID(fld.name()); // name 1.872 + writer->write_u1(sig2tag(sig)); // type 1.873 + } 1.874 + } 1.875 +} 1.876 + 1.877 +// creates HPROF_GC_INSTANCE_DUMP record for the given object 1.878 +void DumperSupport::dump_instance(DumpWriter* writer, oop o) { 1.879 + Klass* k = o->klass(); 1.880 + 1.881 + writer->write_u1(HPROF_GC_INSTANCE_DUMP); 1.882 + writer->write_objectID(o); 1.883 + writer->write_u4(STACK_TRACE_ID); 1.884 + 1.885 + // class ID 1.886 + writer->write_classID(k); 1.887 + 1.888 + // number of bytes that follow 1.889 + writer->write_u4(instance_size(k) ); 1.890 + 1.891 + // field values 1.892 + dump_instance_fields(writer, o); 1.893 +} 1.894 + 1.895 +// creates HPROF_GC_CLASS_DUMP record for the given class and each of 1.896 +// its array classes 1.897 +void DumperSupport::dump_class_and_array_classes(DumpWriter* writer, Klass* k) { 1.898 + Klass* klass = k; 1.899 + assert(klass->oop_is_instance(), "not an InstanceKlass"); 1.900 + InstanceKlass* ik = (InstanceKlass*)klass; 1.901 + 1.902 + writer->write_u1(HPROF_GC_CLASS_DUMP); 1.903 + 1.904 + // class ID 1.905 + writer->write_classID(ik); 1.906 + writer->write_u4(STACK_TRACE_ID); 1.907 + 1.908 + // super class ID 1.909 + Klass* java_super = ik->java_super(); 1.910 + if (java_super == NULL) { 1.911 + writer->write_objectID(oop(NULL)); 1.912 + } else { 1.913 + writer->write_classID(java_super); 1.914 + } 1.915 + 1.916 + writer->write_objectID(ik->class_loader()); 1.917 + writer->write_objectID(ik->signers()); 1.918 + writer->write_objectID(ik->protection_domain()); 1.919 + 1.920 + // reserved 1.921 + writer->write_objectID(oop(NULL)); 1.922 + writer->write_objectID(oop(NULL)); 1.923 + 1.924 + // instance size 1.925 + writer->write_u4(DumperSupport::instance_size(k)); 1.926 + 1.927 + // size of constant pool - ignored by HAT 1.1 1.928 + writer->write_u2(0); 1.929 + 1.930 + // number of static fields 1.931 + dump_static_fields(writer, k); 1.932 + 1.933 + // description of instance fields 1.934 + dump_instance_field_descriptors(writer, k); 1.935 + 1.936 + // array classes 1.937 + k = klass->array_klass_or_null(); 1.938 + while (k != NULL) { 1.939 + Klass* klass = k; 1.940 + assert(klass->oop_is_objArray(), "not an ObjArrayKlass"); 1.941 + 1.942 + writer->write_u1(HPROF_GC_CLASS_DUMP); 1.943 + writer->write_classID(klass); 1.944 + writer->write_u4(STACK_TRACE_ID); 1.945 + 1.946 + // super class of array classes is java.lang.Object 1.947 + java_super = klass->java_super(); 1.948 + assert(java_super != NULL, "checking"); 1.949 + writer->write_classID(java_super); 1.950 + 1.951 + writer->write_objectID(ik->class_loader()); 1.952 + writer->write_objectID(ik->signers()); 1.953 + writer->write_objectID(ik->protection_domain()); 1.954 + 1.955 + writer->write_objectID(oop(NULL)); // reserved 1.956 + writer->write_objectID(oop(NULL)); 1.957 + writer->write_u4(0); // instance size 1.958 + writer->write_u2(0); // constant pool 1.959 + writer->write_u2(0); // static fields 1.960 + writer->write_u2(0); // instance fields 1.961 + 1.962 + // get the array class for the next rank 1.963 + k = klass->array_klass_or_null(); 1.964 + } 1.965 +} 1.966 + 1.967 +// creates HPROF_GC_CLASS_DUMP record for a given primitive array 1.968 +// class (and each multi-dimensional array class too) 1.969 +void DumperSupport::dump_basic_type_array_class(DumpWriter* writer, Klass* k) { 1.970 + // array classes 1.971 + while (k != NULL) { 1.972 + Klass* klass = k; 1.973 + 1.974 + writer->write_u1(HPROF_GC_CLASS_DUMP); 1.975 + writer->write_classID(klass); 1.976 + writer->write_u4(STACK_TRACE_ID); 1.977 + 1.978 + // super class of array classes is java.lang.Object 1.979 + Klass* java_super = klass->java_super(); 1.980 + assert(java_super != NULL, "checking"); 1.981 + writer->write_classID(java_super); 1.982 + 1.983 + writer->write_objectID(oop(NULL)); // loader 1.984 + writer->write_objectID(oop(NULL)); // signers 1.985 + writer->write_objectID(oop(NULL)); // protection domain 1.986 + 1.987 + writer->write_objectID(oop(NULL)); // reserved 1.988 + writer->write_objectID(oop(NULL)); 1.989 + writer->write_u4(0); // instance size 1.990 + writer->write_u2(0); // constant pool 1.991 + writer->write_u2(0); // static fields 1.992 + writer->write_u2(0); // instance fields 1.993 + 1.994 + // get the array class for the next rank 1.995 + k = klass->array_klass_or_null(); 1.996 + } 1.997 +} 1.998 + 1.999 +// creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array 1.1000 +void DumperSupport::dump_object_array(DumpWriter* writer, objArrayOop array) { 1.1001 + 1.1002 + writer->write_u1(HPROF_GC_OBJ_ARRAY_DUMP); 1.1003 + writer->write_objectID(array); 1.1004 + writer->write_u4(STACK_TRACE_ID); 1.1005 + writer->write_u4((u4)array->length()); 1.1006 + 1.1007 + // array class ID 1.1008 + writer->write_classID(array->klass()); 1.1009 + 1.1010 + // [id]* elements 1.1011 + for (int index=0; index<array->length(); index++) { 1.1012 + oop o = array->obj_at(index); 1.1013 + writer->write_objectID(o); 1.1014 + } 1.1015 +} 1.1016 + 1.1017 +#define WRITE_ARRAY(Array, Type, Size) \ 1.1018 + for (int i=0; i<Array->length(); i++) { writer->write_##Size((Size)array->Type##_at(i)); } 1.1019 + 1.1020 + 1.1021 +// creates HPROF_GC_PRIM_ARRAY_DUMP record for the given type array 1.1022 +void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { 1.1023 + BasicType type = TypeArrayKlass::cast(array->klass())->element_type(); 1.1024 + 1.1025 + writer->write_u1(HPROF_GC_PRIM_ARRAY_DUMP); 1.1026 + writer->write_objectID(array); 1.1027 + writer->write_u4(STACK_TRACE_ID); 1.1028 + writer->write_u4((u4)array->length()); 1.1029 + writer->write_u1(type2tag(type)); 1.1030 + 1.1031 + // nothing to copy 1.1032 + if (array->length() == 0) { 1.1033 + return; 1.1034 + } 1.1035 + 1.1036 + // If the byte ordering is big endian then we can copy most types directly 1.1037 + int length_in_bytes = array->length() * type2aelembytes(type); 1.1038 + assert(length_in_bytes > 0, "nothing to copy"); 1.1039 + 1.1040 + switch (type) { 1.1041 + case T_INT : { 1.1042 + if (Bytes::is_Java_byte_ordering_different()) { 1.1043 + WRITE_ARRAY(array, int, u4); 1.1044 + } else { 1.1045 + writer->write_raw((void*)(array->int_at_addr(0)), length_in_bytes); 1.1046 + } 1.1047 + break; 1.1048 + } 1.1049 + case T_BYTE : { 1.1050 + writer->write_raw((void*)(array->byte_at_addr(0)), length_in_bytes); 1.1051 + break; 1.1052 + } 1.1053 + case T_CHAR : { 1.1054 + if (Bytes::is_Java_byte_ordering_different()) { 1.1055 + WRITE_ARRAY(array, char, u2); 1.1056 + } else { 1.1057 + writer->write_raw((void*)(array->char_at_addr(0)), length_in_bytes); 1.1058 + } 1.1059 + break; 1.1060 + } 1.1061 + case T_SHORT : { 1.1062 + if (Bytes::is_Java_byte_ordering_different()) { 1.1063 + WRITE_ARRAY(array, short, u2); 1.1064 + } else { 1.1065 + writer->write_raw((void*)(array->short_at_addr(0)), length_in_bytes); 1.1066 + } 1.1067 + break; 1.1068 + } 1.1069 + case T_BOOLEAN : { 1.1070 + if (Bytes::is_Java_byte_ordering_different()) { 1.1071 + WRITE_ARRAY(array, bool, u1); 1.1072 + } else { 1.1073 + writer->write_raw((void*)(array->bool_at_addr(0)), length_in_bytes); 1.1074 + } 1.1075 + break; 1.1076 + } 1.1077 + case T_LONG : { 1.1078 + if (Bytes::is_Java_byte_ordering_different()) { 1.1079 + WRITE_ARRAY(array, long, u8); 1.1080 + } else { 1.1081 + writer->write_raw((void*)(array->long_at_addr(0)), length_in_bytes); 1.1082 + } 1.1083 + break; 1.1084 + } 1.1085 + 1.1086 + // handle float/doubles in a special value to ensure than NaNs are 1.1087 + // written correctly. TO DO: Check if we can avoid this on processors that 1.1088 + // use IEEE 754. 1.1089 + 1.1090 + case T_FLOAT : { 1.1091 + for (int i=0; i<array->length(); i++) { 1.1092 + dump_float( writer, array->float_at(i) ); 1.1093 + } 1.1094 + break; 1.1095 + } 1.1096 + case T_DOUBLE : { 1.1097 + for (int i=0; i<array->length(); i++) { 1.1098 + dump_double( writer, array->double_at(i) ); 1.1099 + } 1.1100 + break; 1.1101 + } 1.1102 + default : ShouldNotReachHere(); 1.1103 + } 1.1104 +} 1.1105 + 1.1106 +// create a HPROF_FRAME record of the given Method* and bci 1.1107 +void DumperSupport::dump_stack_frame(DumpWriter* writer, 1.1108 + int frame_serial_num, 1.1109 + int class_serial_num, 1.1110 + Method* m, 1.1111 + int bci) { 1.1112 + int line_number; 1.1113 + if (m->is_native()) { 1.1114 + line_number = -3; // native frame 1.1115 + } else { 1.1116 + line_number = m->line_number_from_bci(bci); 1.1117 + } 1.1118 + 1.1119 + write_header(writer, HPROF_FRAME, 4*oopSize + 2*sizeof(u4)); 1.1120 + writer->write_id(frame_serial_num); // frame serial number 1.1121 + writer->write_symbolID(m->name()); // method's name 1.1122 + writer->write_symbolID(m->signature()); // method's signature 1.1123 + 1.1124 + assert(m->method_holder()->oop_is_instance(), "not InstanceKlass"); 1.1125 + writer->write_symbolID(m->method_holder()->source_file_name()); // source file name 1.1126 + writer->write_u4(class_serial_num); // class serial number 1.1127 + writer->write_u4((u4) line_number); // line number 1.1128 +} 1.1129 + 1.1130 + 1.1131 +// Support class used to generate HPROF_UTF8 records from the entries in the 1.1132 +// SymbolTable. 1.1133 + 1.1134 +class SymbolTableDumper : public SymbolClosure { 1.1135 + private: 1.1136 + DumpWriter* _writer; 1.1137 + DumpWriter* writer() const { return _writer; } 1.1138 + public: 1.1139 + SymbolTableDumper(DumpWriter* writer) { _writer = writer; } 1.1140 + void do_symbol(Symbol** p); 1.1141 +}; 1.1142 + 1.1143 +void SymbolTableDumper::do_symbol(Symbol** p) { 1.1144 + ResourceMark rm; 1.1145 + Symbol* sym = load_symbol(p); 1.1146 + int len = sym->utf8_length(); 1.1147 + if (len > 0) { 1.1148 + char* s = sym->as_utf8(); 1.1149 + DumperSupport::write_header(writer(), HPROF_UTF8, oopSize + len); 1.1150 + writer()->write_symbolID(sym); 1.1151 + writer()->write_raw(s, len); 1.1152 + } 1.1153 +} 1.1154 + 1.1155 +// Support class used to generate HPROF_GC_ROOT_JNI_LOCAL records 1.1156 + 1.1157 +class JNILocalsDumper : public OopClosure { 1.1158 + private: 1.1159 + DumpWriter* _writer; 1.1160 + u4 _thread_serial_num; 1.1161 + int _frame_num; 1.1162 + DumpWriter* writer() const { return _writer; } 1.1163 + public: 1.1164 + JNILocalsDumper(DumpWriter* writer, u4 thread_serial_num) { 1.1165 + _writer = writer; 1.1166 + _thread_serial_num = thread_serial_num; 1.1167 + _frame_num = -1; // default - empty stack 1.1168 + } 1.1169 + void set_frame_number(int n) { _frame_num = n; } 1.1170 + void do_oop(oop* obj_p); 1.1171 + void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } 1.1172 +}; 1.1173 + 1.1174 + 1.1175 +void JNILocalsDumper::do_oop(oop* obj_p) { 1.1176 + // ignore null or deleted handles 1.1177 + oop o = *obj_p; 1.1178 + if (o != NULL && o != JNIHandles::deleted_handle()) { 1.1179 + writer()->write_u1(HPROF_GC_ROOT_JNI_LOCAL); 1.1180 + writer()->write_objectID(o); 1.1181 + writer()->write_u4(_thread_serial_num); 1.1182 + writer()->write_u4((u4)_frame_num); 1.1183 + } 1.1184 +} 1.1185 + 1.1186 + 1.1187 +// Support class used to generate HPROF_GC_ROOT_JNI_GLOBAL records 1.1188 + 1.1189 +class JNIGlobalsDumper : public OopClosure { 1.1190 + private: 1.1191 + DumpWriter* _writer; 1.1192 + DumpWriter* writer() const { return _writer; } 1.1193 + 1.1194 + public: 1.1195 + JNIGlobalsDumper(DumpWriter* writer) { 1.1196 + _writer = writer; 1.1197 + } 1.1198 + void do_oop(oop* obj_p); 1.1199 + void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } 1.1200 +}; 1.1201 + 1.1202 +void JNIGlobalsDumper::do_oop(oop* obj_p) { 1.1203 + oop o = *obj_p; 1.1204 + 1.1205 + // ignore these 1.1206 + if (o == NULL || o == JNIHandles::deleted_handle()) return; 1.1207 + 1.1208 + // we ignore global ref to symbols and other internal objects 1.1209 + if (o->is_instance() || o->is_objArray() || o->is_typeArray()) { 1.1210 + writer()->write_u1(HPROF_GC_ROOT_JNI_GLOBAL); 1.1211 + writer()->write_objectID(o); 1.1212 + writer()->write_objectID((oopDesc*)obj_p); // global ref ID 1.1213 + } 1.1214 +}; 1.1215 + 1.1216 + 1.1217 +// Support class used to generate HPROF_GC_ROOT_MONITOR_USED records 1.1218 + 1.1219 +class MonitorUsedDumper : public OopClosure { 1.1220 + private: 1.1221 + DumpWriter* _writer; 1.1222 + DumpWriter* writer() const { return _writer; } 1.1223 + public: 1.1224 + MonitorUsedDumper(DumpWriter* writer) { 1.1225 + _writer = writer; 1.1226 + } 1.1227 + void do_oop(oop* obj_p) { 1.1228 + writer()->write_u1(HPROF_GC_ROOT_MONITOR_USED); 1.1229 + writer()->write_objectID(*obj_p); 1.1230 + } 1.1231 + void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } 1.1232 +}; 1.1233 + 1.1234 + 1.1235 +// Support class used to generate HPROF_GC_ROOT_STICKY_CLASS records 1.1236 + 1.1237 +class StickyClassDumper : public KlassClosure { 1.1238 + private: 1.1239 + DumpWriter* _writer; 1.1240 + DumpWriter* writer() const { return _writer; } 1.1241 + public: 1.1242 + StickyClassDumper(DumpWriter* writer) { 1.1243 + _writer = writer; 1.1244 + } 1.1245 + void do_klass(Klass* k) { 1.1246 + if (k->oop_is_instance()) { 1.1247 + InstanceKlass* ik = InstanceKlass::cast(k); 1.1248 + writer()->write_u1(HPROF_GC_ROOT_STICKY_CLASS); 1.1249 + writer()->write_classID(ik); 1.1250 + } 1.1251 + } 1.1252 +}; 1.1253 + 1.1254 + 1.1255 +class VM_HeapDumper; 1.1256 + 1.1257 +// Support class using when iterating over the heap. 1.1258 + 1.1259 +class HeapObjectDumper : public ObjectClosure { 1.1260 + private: 1.1261 + VM_HeapDumper* _dumper; 1.1262 + DumpWriter* _writer; 1.1263 + 1.1264 + VM_HeapDumper* dumper() { return _dumper; } 1.1265 + DumpWriter* writer() { return _writer; } 1.1266 + 1.1267 + // used to indicate that a record has been writen 1.1268 + void mark_end_of_record(); 1.1269 + 1.1270 + public: 1.1271 + HeapObjectDumper(VM_HeapDumper* dumper, DumpWriter* writer) { 1.1272 + _dumper = dumper; 1.1273 + _writer = writer; 1.1274 + } 1.1275 + 1.1276 + // called for each object in the heap 1.1277 + void do_object(oop o); 1.1278 +}; 1.1279 + 1.1280 +void HeapObjectDumper::do_object(oop o) { 1.1281 + // hide the sentinel for deleted handles 1.1282 + if (o == JNIHandles::deleted_handle()) return; 1.1283 + 1.1284 + // skip classes as these emitted as HPROF_GC_CLASS_DUMP records 1.1285 + if (o->klass() == SystemDictionary::Class_klass()) { 1.1286 + if (!java_lang_Class::is_primitive(o)) { 1.1287 + return; 1.1288 + } 1.1289 + } 1.1290 + 1.1291 + // create a HPROF_GC_INSTANCE record for each object 1.1292 + if (o->is_instance()) { 1.1293 + DumperSupport::dump_instance(writer(), o); 1.1294 + mark_end_of_record(); 1.1295 + } else { 1.1296 + // create a HPROF_GC_OBJ_ARRAY_DUMP record for each object array 1.1297 + if (o->is_objArray()) { 1.1298 + DumperSupport::dump_object_array(writer(), objArrayOop(o)); 1.1299 + mark_end_of_record(); 1.1300 + } else { 1.1301 + // create a HPROF_GC_PRIM_ARRAY_DUMP record for each type array 1.1302 + if (o->is_typeArray()) { 1.1303 + DumperSupport::dump_prim_array(writer(), typeArrayOop(o)); 1.1304 + mark_end_of_record(); 1.1305 + } 1.1306 + } 1.1307 + } 1.1308 +} 1.1309 + 1.1310 +// The VM operation that performs the heap dump 1.1311 +class VM_HeapDumper : public VM_GC_Operation { 1.1312 + private: 1.1313 + static VM_HeapDumper* _global_dumper; 1.1314 + static DumpWriter* _global_writer; 1.1315 + DumpWriter* _local_writer; 1.1316 + JavaThread* _oome_thread; 1.1317 + Method* _oome_constructor; 1.1318 + bool _gc_before_heap_dump; 1.1319 + bool _is_segmented_dump; 1.1320 + jlong _dump_start; 1.1321 + GrowableArray<Klass*>* _klass_map; 1.1322 + ThreadStackTrace** _stack_traces; 1.1323 + int _num_threads; 1.1324 + 1.1325 + // accessors and setters 1.1326 + static VM_HeapDumper* dumper() { assert(_global_dumper != NULL, "Error"); return _global_dumper; } 1.1327 + static DumpWriter* writer() { assert(_global_writer != NULL, "Error"); return _global_writer; } 1.1328 + void set_global_dumper() { 1.1329 + assert(_global_dumper == NULL, "Error"); 1.1330 + _global_dumper = this; 1.1331 + } 1.1332 + void set_global_writer() { 1.1333 + assert(_global_writer == NULL, "Error"); 1.1334 + _global_writer = _local_writer; 1.1335 + } 1.1336 + void clear_global_dumper() { _global_dumper = NULL; } 1.1337 + void clear_global_writer() { _global_writer = NULL; } 1.1338 + 1.1339 + bool is_segmented_dump() const { return _is_segmented_dump; } 1.1340 + void set_segmented_dump() { _is_segmented_dump = true; } 1.1341 + jlong dump_start() const { return _dump_start; } 1.1342 + void set_dump_start(jlong pos); 1.1343 + 1.1344 + bool skip_operation() const; 1.1345 + 1.1346 + // writes a HPROF_LOAD_CLASS record 1.1347 + static void do_load_class(Klass* k); 1.1348 + 1.1349 + // writes a HPROF_GC_CLASS_DUMP record for the given class 1.1350 + // (and each array class too) 1.1351 + static void do_class_dump(Klass* k); 1.1352 + 1.1353 + // writes a HPROF_GC_CLASS_DUMP records for a given basic type 1.1354 + // array (and each multi-dimensional array too) 1.1355 + static void do_basic_type_array_class_dump(Klass* k); 1.1356 + 1.1357 + // HPROF_GC_ROOT_THREAD_OBJ records 1.1358 + int do_thread(JavaThread* thread, u4 thread_serial_num); 1.1359 + void do_threads(); 1.1360 + 1.1361 + void add_class_serial_number(Klass* k, int serial_num) { 1.1362 + _klass_map->at_put_grow(serial_num, k); 1.1363 + } 1.1364 + 1.1365 + // HPROF_TRACE and HPROF_FRAME records 1.1366 + void dump_stack_traces(); 1.1367 + 1.1368 + // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record 1.1369 + void write_dump_header(); 1.1370 + 1.1371 + // fixes up the length of the current dump record 1.1372 + void write_current_dump_record_length(); 1.1373 + 1.1374 + // fixes up the current dump record )and writes HPROF_HEAP_DUMP_END 1.1375 + // record in the case of a segmented heap dump) 1.1376 + void end_of_dump(); 1.1377 + 1.1378 + public: 1.1379 + VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump, bool oome) : 1.1380 + VM_GC_Operation(0 /* total collections, dummy, ignored */, 1.1381 + GCCause::_heap_dump /* GC Cause */, 1.1382 + 0 /* total full collections, dummy, ignored */, 1.1383 + gc_before_heap_dump) { 1.1384 + _local_writer = writer; 1.1385 + _gc_before_heap_dump = gc_before_heap_dump; 1.1386 + _is_segmented_dump = false; 1.1387 + _dump_start = (jlong)-1; 1.1388 + _klass_map = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, true); 1.1389 + _stack_traces = NULL; 1.1390 + _num_threads = 0; 1.1391 + if (oome) { 1.1392 + assert(!Thread::current()->is_VM_thread(), "Dump from OutOfMemoryError cannot be called by the VMThread"); 1.1393 + // get OutOfMemoryError zero-parameter constructor 1.1394 + InstanceKlass* oome_ik = InstanceKlass::cast(SystemDictionary::OutOfMemoryError_klass()); 1.1395 + _oome_constructor = oome_ik->find_method(vmSymbols::object_initializer_name(), 1.1396 + vmSymbols::void_method_signature()); 1.1397 + // get thread throwing OOME when generating the heap dump at OOME 1.1398 + _oome_thread = JavaThread::current(); 1.1399 + } else { 1.1400 + _oome_thread = NULL; 1.1401 + _oome_constructor = NULL; 1.1402 + } 1.1403 + } 1.1404 + ~VM_HeapDumper() { 1.1405 + if (_stack_traces != NULL) { 1.1406 + for (int i=0; i < _num_threads; i++) { 1.1407 + delete _stack_traces[i]; 1.1408 + } 1.1409 + FREE_C_HEAP_ARRAY(ThreadStackTrace*, _stack_traces, mtInternal); 1.1410 + } 1.1411 + delete _klass_map; 1.1412 + } 1.1413 + 1.1414 + VMOp_Type type() const { return VMOp_HeapDumper; } 1.1415 + // used to mark sub-record boundary 1.1416 + void check_segment_length(); 1.1417 + void doit(); 1.1418 +}; 1.1419 + 1.1420 +VM_HeapDumper* VM_HeapDumper::_global_dumper = NULL; 1.1421 +DumpWriter* VM_HeapDumper::_global_writer = NULL; 1.1422 + 1.1423 +bool VM_HeapDumper::skip_operation() const { 1.1424 + return false; 1.1425 +} 1.1426 + 1.1427 +// sets the dump starting position 1.1428 +void VM_HeapDumper::set_dump_start(jlong pos) { 1.1429 + _dump_start = pos; 1.1430 +} 1.1431 + 1.1432 + // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record 1.1433 +void VM_HeapDumper::write_dump_header() { 1.1434 + if (writer()->is_open()) { 1.1435 + if (is_segmented_dump()) { 1.1436 + writer()->write_u1(HPROF_HEAP_DUMP_SEGMENT); 1.1437 + } else { 1.1438 + writer()->write_u1(HPROF_HEAP_DUMP); 1.1439 + } 1.1440 + writer()->write_u4(0); // current ticks 1.1441 + 1.1442 + // record the starting position for the dump (its length will be fixed up later) 1.1443 + set_dump_start(writer()->current_offset()); 1.1444 + writer()->write_u4(0); 1.1445 + } 1.1446 +} 1.1447 + 1.1448 +// fixes up the length of the current dump record 1.1449 +void VM_HeapDumper::write_current_dump_record_length() { 1.1450 + if (writer()->is_open()) { 1.1451 + assert(dump_start() >= 0, "no dump start recorded"); 1.1452 + 1.1453 + // calculate the size of the dump record 1.1454 + jlong dump_end = writer()->current_offset(); 1.1455 + jlong dump_len = (dump_end - dump_start() - 4); 1.1456 + 1.1457 + // record length must fit in a u4 1.1458 + if (dump_len > (jlong)(4L*(jlong)G)) { 1.1459 + warning("record is too large"); 1.1460 + } 1.1461 + 1.1462 + // seek to the dump start and fix-up the length 1.1463 + writer()->seek_to_offset(dump_start()); 1.1464 + writer()->write_u4((u4)dump_len); 1.1465 + 1.1466 + // adjust the total size written to keep the bytes written correct. 1.1467 + writer()->adjust_bytes_written(-((long) sizeof(u4))); 1.1468 + 1.1469 + // seek to dump end so we can continue 1.1470 + writer()->seek_to_offset(dump_end); 1.1471 + 1.1472 + // no current dump record 1.1473 + set_dump_start((jlong)-1); 1.1474 + } 1.1475 +} 1.1476 + 1.1477 +// used on a sub-record boundary to check if we need to start a 1.1478 +// new segment. 1.1479 +void VM_HeapDumper::check_segment_length() { 1.1480 + if (writer()->is_open()) { 1.1481 + if (is_segmented_dump()) { 1.1482 + // don't use current_offset that would be too expensive on a per record basis 1.1483 + jlong dump_end = writer()->bytes_written() + writer()->bytes_unwritten(); 1.1484 + assert(dump_end == writer()->current_offset(), "checking"); 1.1485 + jlong dump_len = (dump_end - dump_start() - 4); 1.1486 + assert(dump_len >= 0 && dump_len <= max_juint, "bad dump length"); 1.1487 + 1.1488 + if (dump_len > (jlong)HeapDumpSegmentSize) { 1.1489 + write_current_dump_record_length(); 1.1490 + write_dump_header(); 1.1491 + } 1.1492 + } 1.1493 + } 1.1494 +} 1.1495 + 1.1496 +// fixes up the current dump record )and writes HPROF_HEAP_DUMP_END 1.1497 +// record in the case of a segmented heap dump) 1.1498 +void VM_HeapDumper::end_of_dump() { 1.1499 + if (writer()->is_open()) { 1.1500 + write_current_dump_record_length(); 1.1501 + 1.1502 + // for segmented dump we write the end record 1.1503 + if (is_segmented_dump()) { 1.1504 + writer()->write_u1(HPROF_HEAP_DUMP_END); 1.1505 + writer()->write_u4(0); 1.1506 + writer()->write_u4(0); 1.1507 + } 1.1508 + } 1.1509 +} 1.1510 + 1.1511 +// marks sub-record boundary 1.1512 +void HeapObjectDumper::mark_end_of_record() { 1.1513 + dumper()->check_segment_length(); 1.1514 +} 1.1515 + 1.1516 +// writes a HPROF_LOAD_CLASS record for the class (and each of its 1.1517 +// array classes) 1.1518 +void VM_HeapDumper::do_load_class(Klass* k) { 1.1519 + static u4 class_serial_num = 0; 1.1520 + 1.1521 + // len of HPROF_LOAD_CLASS record 1.1522 + u4 remaining = 2*oopSize + 2*sizeof(u4); 1.1523 + 1.1524 + // write a HPROF_LOAD_CLASS for the class and each array class 1.1525 + do { 1.1526 + DumperSupport::write_header(writer(), HPROF_LOAD_CLASS, remaining); 1.1527 + 1.1528 + // class serial number is just a number 1.1529 + writer()->write_u4(++class_serial_num); 1.1530 + 1.1531 + // class ID 1.1532 + Klass* klass = k; 1.1533 + writer()->write_classID(klass); 1.1534 + 1.1535 + // add the Klass* and class serial number pair 1.1536 + dumper()->add_class_serial_number(klass, class_serial_num); 1.1537 + 1.1538 + writer()->write_u4(STACK_TRACE_ID); 1.1539 + 1.1540 + // class name ID 1.1541 + Symbol* name = klass->name(); 1.1542 + writer()->write_symbolID(name); 1.1543 + 1.1544 + // write a LOAD_CLASS record for the array type (if it exists) 1.1545 + k = klass->array_klass_or_null(); 1.1546 + } while (k != NULL); 1.1547 +} 1.1548 + 1.1549 +// writes a HPROF_GC_CLASS_DUMP record for the given class 1.1550 +void VM_HeapDumper::do_class_dump(Klass* k) { 1.1551 + if (k->oop_is_instance()) { 1.1552 + DumperSupport::dump_class_and_array_classes(writer(), k); 1.1553 + } 1.1554 +} 1.1555 + 1.1556 +// writes a HPROF_GC_CLASS_DUMP records for a given basic type 1.1557 +// array (and each multi-dimensional array too) 1.1558 +void VM_HeapDumper::do_basic_type_array_class_dump(Klass* k) { 1.1559 + DumperSupport::dump_basic_type_array_class(writer(), k); 1.1560 +} 1.1561 + 1.1562 +// Walk the stack of the given thread. 1.1563 +// Dumps a HPROF_GC_ROOT_JAVA_FRAME record for each local 1.1564 +// Dumps a HPROF_GC_ROOT_JNI_LOCAL record for each JNI local 1.1565 +// 1.1566 +// It returns the number of Java frames in this thread stack 1.1567 +int VM_HeapDumper::do_thread(JavaThread* java_thread, u4 thread_serial_num) { 1.1568 + JNILocalsDumper blk(writer(), thread_serial_num); 1.1569 + 1.1570 + oop threadObj = java_thread->threadObj(); 1.1571 + assert(threadObj != NULL, "sanity check"); 1.1572 + 1.1573 + int stack_depth = 0; 1.1574 + if (java_thread->has_last_Java_frame()) { 1.1575 + 1.1576 + // vframes are resource allocated 1.1577 + Thread* current_thread = Thread::current(); 1.1578 + ResourceMark rm(current_thread); 1.1579 + HandleMark hm(current_thread); 1.1580 + 1.1581 + RegisterMap reg_map(java_thread); 1.1582 + frame f = java_thread->last_frame(); 1.1583 + vframe* vf = vframe::new_vframe(&f, ®_map, java_thread); 1.1584 + frame* last_entry_frame = NULL; 1.1585 + int extra_frames = 0; 1.1586 + 1.1587 + if (java_thread == _oome_thread && _oome_constructor != NULL) { 1.1588 + extra_frames++; 1.1589 + } 1.1590 + while (vf != NULL) { 1.1591 + blk.set_frame_number(stack_depth); 1.1592 + if (vf->is_java_frame()) { 1.1593 + 1.1594 + // java frame (interpreted, compiled, ...) 1.1595 + javaVFrame *jvf = javaVFrame::cast(vf); 1.1596 + if (!(jvf->method()->is_native())) { 1.1597 + StackValueCollection* locals = jvf->locals(); 1.1598 + for (int slot=0; slot<locals->size(); slot++) { 1.1599 + if (locals->at(slot)->type() == T_OBJECT) { 1.1600 + oop o = locals->obj_at(slot)(); 1.1601 + 1.1602 + if (o != NULL) { 1.1603 + writer()->write_u1(HPROF_GC_ROOT_JAVA_FRAME); 1.1604 + writer()->write_objectID(o); 1.1605 + writer()->write_u4(thread_serial_num); 1.1606 + writer()->write_u4((u4) (stack_depth + extra_frames)); 1.1607 + } 1.1608 + } 1.1609 + } 1.1610 + } else { 1.1611 + // native frame 1.1612 + if (stack_depth == 0) { 1.1613 + // JNI locals for the top frame. 1.1614 + java_thread->active_handles()->oops_do(&blk); 1.1615 + } else { 1.1616 + if (last_entry_frame != NULL) { 1.1617 + // JNI locals for the entry frame 1.1618 + assert(last_entry_frame->is_entry_frame(), "checking"); 1.1619 + last_entry_frame->entry_frame_call_wrapper()->handles()->oops_do(&blk); 1.1620 + } 1.1621 + } 1.1622 + } 1.1623 + // increment only for Java frames 1.1624 + stack_depth++; 1.1625 + last_entry_frame = NULL; 1.1626 + 1.1627 + } else { 1.1628 + // externalVFrame - if it's an entry frame then report any JNI locals 1.1629 + // as roots when we find the corresponding native javaVFrame 1.1630 + frame* fr = vf->frame_pointer(); 1.1631 + assert(fr != NULL, "sanity check"); 1.1632 + if (fr->is_entry_frame()) { 1.1633 + last_entry_frame = fr; 1.1634 + } 1.1635 + } 1.1636 + vf = vf->sender(); 1.1637 + } 1.1638 + } else { 1.1639 + // no last java frame but there may be JNI locals 1.1640 + java_thread->active_handles()->oops_do(&blk); 1.1641 + } 1.1642 + return stack_depth; 1.1643 +} 1.1644 + 1.1645 + 1.1646 +// write a HPROF_GC_ROOT_THREAD_OBJ record for each java thread. Then walk 1.1647 +// the stack so that locals and JNI locals are dumped. 1.1648 +void VM_HeapDumper::do_threads() { 1.1649 + for (int i=0; i < _num_threads; i++) { 1.1650 + JavaThread* thread = _stack_traces[i]->thread(); 1.1651 + oop threadObj = thread->threadObj(); 1.1652 + u4 thread_serial_num = i+1; 1.1653 + u4 stack_serial_num = thread_serial_num + STACK_TRACE_ID; 1.1654 + writer()->write_u1(HPROF_GC_ROOT_THREAD_OBJ); 1.1655 + writer()->write_objectID(threadObj); 1.1656 + writer()->write_u4(thread_serial_num); // thread number 1.1657 + writer()->write_u4(stack_serial_num); // stack trace serial number 1.1658 + int num_frames = do_thread(thread, thread_serial_num); 1.1659 + assert(num_frames == _stack_traces[i]->get_stack_depth(), 1.1660 + "total number of Java frames not matched"); 1.1661 + } 1.1662 +} 1.1663 + 1.1664 + 1.1665 +// The VM operation that dumps the heap. The dump consists of the following 1.1666 +// records: 1.1667 +// 1.1668 +// HPROF_HEADER 1.1669 +// [HPROF_UTF8]* 1.1670 +// [HPROF_LOAD_CLASS]* 1.1671 +// [[HPROF_FRAME]*|HPROF_TRACE]* 1.1672 +// [HPROF_GC_CLASS_DUMP]* 1.1673 +// HPROF_HEAP_DUMP 1.1674 +// 1.1675 +// The HPROF_TRACE records represent the stack traces where the heap dump 1.1676 +// is generated and a "dummy trace" record which does not include 1.1677 +// any frames. The dummy trace record is used to be referenced as the 1.1678 +// unknown object alloc site. 1.1679 +// 1.1680 +// The HPROF_HEAP_DUMP record has a length following by sub-records. To allow 1.1681 +// the heap dump be generated in a single pass we remember the position of 1.1682 +// the dump length and fix it up after all sub-records have been written. 1.1683 +// To generate the sub-records we iterate over the heap, writing 1.1684 +// HPROF_GC_INSTANCE_DUMP, HPROF_GC_OBJ_ARRAY_DUMP, and HPROF_GC_PRIM_ARRAY_DUMP 1.1685 +// records as we go. Once that is done we write records for some of the GC 1.1686 +// roots. 1.1687 + 1.1688 +void VM_HeapDumper::doit() { 1.1689 + 1.1690 + HandleMark hm; 1.1691 + CollectedHeap* ch = Universe::heap(); 1.1692 + 1.1693 + ch->ensure_parsability(false); // must happen, even if collection does 1.1694 + // not happen (e.g. due to GC_locker) 1.1695 + 1.1696 + if (_gc_before_heap_dump) { 1.1697 + if (GC_locker::is_active()) { 1.1698 + warning("GC locker is held; pre-heapdump GC was skipped"); 1.1699 + } else { 1.1700 + ch->collect_as_vm_thread(GCCause::_heap_dump); 1.1701 + } 1.1702 + } 1.1703 + 1.1704 + // At this point we should be the only dumper active, so 1.1705 + // the following should be safe. 1.1706 + set_global_dumper(); 1.1707 + set_global_writer(); 1.1708 + 1.1709 + // Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1 1.1710 + size_t used = ch->used(); 1.1711 + const char* header; 1.1712 + if (used > (size_t)SegmentedHeapDumpThreshold) { 1.1713 + set_segmented_dump(); 1.1714 + header = "JAVA PROFILE 1.0.2"; 1.1715 + } else { 1.1716 + header = "JAVA PROFILE 1.0.1"; 1.1717 + } 1.1718 + 1.1719 + // header is few bytes long - no chance to overflow int 1.1720 + writer()->write_raw((void*)header, (int)strlen(header)); 1.1721 + writer()->write_u1(0); // terminator 1.1722 + writer()->write_u4(oopSize); 1.1723 + writer()->write_u8(os::javaTimeMillis()); 1.1724 + 1.1725 + // HPROF_UTF8 records 1.1726 + SymbolTableDumper sym_dumper(writer()); 1.1727 + SymbolTable::symbols_do(&sym_dumper); 1.1728 + 1.1729 + // write HPROF_LOAD_CLASS records 1.1730 + ClassLoaderDataGraph::classes_do(&do_load_class); 1.1731 + Universe::basic_type_classes_do(&do_load_class); 1.1732 + 1.1733 + // write HPROF_FRAME and HPROF_TRACE records 1.1734 + // this must be called after _klass_map is built when iterating the classes above. 1.1735 + dump_stack_traces(); 1.1736 + 1.1737 + // write HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT 1.1738 + write_dump_header(); 1.1739 + 1.1740 + // Writes HPROF_GC_CLASS_DUMP records 1.1741 + ClassLoaderDataGraph::classes_do(&do_class_dump); 1.1742 + Universe::basic_type_classes_do(&do_basic_type_array_class_dump); 1.1743 + check_segment_length(); 1.1744 + 1.1745 + // writes HPROF_GC_INSTANCE_DUMP records. 1.1746 + // After each sub-record is written check_segment_length will be invoked. When 1.1747 + // generated a segmented heap dump this allows us to check if the current 1.1748 + // segment exceeds a threshold and if so, then a new segment is started. 1.1749 + // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk 1.1750 + // of the heap dump. 1.1751 + HeapObjectDumper obj_dumper(this, writer()); 1.1752 + Universe::heap()->safe_object_iterate(&obj_dumper); 1.1753 + 1.1754 + // HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals 1.1755 + do_threads(); 1.1756 + check_segment_length(); 1.1757 + 1.1758 + // HPROF_GC_ROOT_MONITOR_USED 1.1759 + MonitorUsedDumper mon_dumper(writer()); 1.1760 + ObjectSynchronizer::oops_do(&mon_dumper); 1.1761 + check_segment_length(); 1.1762 + 1.1763 + // HPROF_GC_ROOT_JNI_GLOBAL 1.1764 + JNIGlobalsDumper jni_dumper(writer()); 1.1765 + JNIHandles::oops_do(&jni_dumper); 1.1766 + check_segment_length(); 1.1767 + 1.1768 + // HPROF_GC_ROOT_STICKY_CLASS 1.1769 + StickyClassDumper class_dumper(writer()); 1.1770 + SystemDictionary::always_strong_classes_do(&class_dumper); 1.1771 + 1.1772 + // fixes up the length of the dump record. In the case of a segmented 1.1773 + // heap then the HPROF_HEAP_DUMP_END record is also written. 1.1774 + end_of_dump(); 1.1775 + 1.1776 + // Now we clear the global variables, so that a future dumper might run. 1.1777 + clear_global_dumper(); 1.1778 + clear_global_writer(); 1.1779 +} 1.1780 + 1.1781 +void VM_HeapDumper::dump_stack_traces() { 1.1782 + // write a HPROF_TRACE record without any frames to be referenced as object alloc sites 1.1783 + DumperSupport::write_header(writer(), HPROF_TRACE, 3*sizeof(u4)); 1.1784 + writer()->write_u4((u4) STACK_TRACE_ID); 1.1785 + writer()->write_u4(0); // thread number 1.1786 + writer()->write_u4(0); // frame count 1.1787 + 1.1788 + _stack_traces = NEW_C_HEAP_ARRAY(ThreadStackTrace*, Threads::number_of_threads(), mtInternal); 1.1789 + int frame_serial_num = 0; 1.1790 + for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) { 1.1791 + oop threadObj = thread->threadObj(); 1.1792 + if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) { 1.1793 + // dump thread stack trace 1.1794 + ThreadStackTrace* stack_trace = new ThreadStackTrace(thread, false); 1.1795 + stack_trace->dump_stack_at_safepoint(-1); 1.1796 + _stack_traces[_num_threads++] = stack_trace; 1.1797 + 1.1798 + // write HPROF_FRAME records for this thread's stack trace 1.1799 + int depth = stack_trace->get_stack_depth(); 1.1800 + int thread_frame_start = frame_serial_num; 1.1801 + int extra_frames = 0; 1.1802 + // write fake frame that makes it look like the thread, which caused OOME, 1.1803 + // is in the OutOfMemoryError zero-parameter constructor 1.1804 + if (thread == _oome_thread && _oome_constructor != NULL) { 1.1805 + int oome_serial_num = _klass_map->find(_oome_constructor->method_holder()); 1.1806 + // the class serial number starts from 1 1.1807 + assert(oome_serial_num > 0, "OutOfMemoryError class not found"); 1.1808 + DumperSupport::dump_stack_frame(writer(), ++frame_serial_num, oome_serial_num, 1.1809 + _oome_constructor, 0); 1.1810 + extra_frames++; 1.1811 + } 1.1812 + for (int j=0; j < depth; j++) { 1.1813 + StackFrameInfo* frame = stack_trace->stack_frame_at(j); 1.1814 + Method* m = frame->method(); 1.1815 + int class_serial_num = _klass_map->find(m->method_holder()); 1.1816 + // the class serial number starts from 1 1.1817 + assert(class_serial_num > 0, "class not found"); 1.1818 + DumperSupport::dump_stack_frame(writer(), ++frame_serial_num, class_serial_num, m, frame->bci()); 1.1819 + } 1.1820 + depth += extra_frames; 1.1821 + 1.1822 + // write HPROF_TRACE record for one thread 1.1823 + DumperSupport::write_header(writer(), HPROF_TRACE, 3*sizeof(u4) + depth*oopSize); 1.1824 + int stack_serial_num = _num_threads + STACK_TRACE_ID; 1.1825 + writer()->write_u4(stack_serial_num); // stack trace serial number 1.1826 + writer()->write_u4((u4) _num_threads); // thread serial number 1.1827 + writer()->write_u4(depth); // frame count 1.1828 + for (int j=1; j <= depth; j++) { 1.1829 + writer()->write_id(thread_frame_start + j); 1.1830 + } 1.1831 + } 1.1832 + } 1.1833 +} 1.1834 + 1.1835 +// dump the heap to given path. 1.1836 +PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL 1.1837 +int HeapDumper::dump(const char* path) { 1.1838 + assert(path != NULL && strlen(path) > 0, "path missing"); 1.1839 + 1.1840 + // print message in interactive case 1.1841 + if (print_to_tty()) { 1.1842 + tty->print_cr("Dumping heap to %s ...", path); 1.1843 + timer()->start(); 1.1844 + } 1.1845 + 1.1846 + // create the dump writer. If the file can be opened then bail 1.1847 + DumpWriter writer(path); 1.1848 + if (!writer.is_open()) { 1.1849 + set_error(writer.error()); 1.1850 + if (print_to_tty()) { 1.1851 + tty->print_cr("Unable to create %s: %s", path, 1.1852 + (error() != NULL) ? error() : "reason unknown"); 1.1853 + } 1.1854 + return -1; 1.1855 + } 1.1856 + 1.1857 + // generate the dump 1.1858 + VM_HeapDumper dumper(&writer, _gc_before_heap_dump, _oome); 1.1859 + if (Thread::current()->is_VM_thread()) { 1.1860 + assert(SafepointSynchronize::is_at_safepoint(), "Expected to be called at a safepoint"); 1.1861 + dumper.doit(); 1.1862 + } else { 1.1863 + VMThread::execute(&dumper); 1.1864 + } 1.1865 + 1.1866 + // close dump file and record any error that the writer may have encountered 1.1867 + writer.close(); 1.1868 + set_error(writer.error()); 1.1869 + 1.1870 + // print message in interactive case 1.1871 + if (print_to_tty()) { 1.1872 + timer()->stop(); 1.1873 + if (error() == NULL) { 1.1874 + char msg[256]; 1.1875 + sprintf(msg, "Heap dump file created [%s bytes in %3.3f secs]", 1.1876 + JLONG_FORMAT, timer()->seconds()); 1.1877 +PRAGMA_DIAG_PUSH 1.1878 +PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL 1.1879 + tty->print_cr(msg, writer.bytes_written()); 1.1880 +PRAGMA_DIAG_POP 1.1881 + } else { 1.1882 + tty->print_cr("Dump file is incomplete: %s", writer.error()); 1.1883 + } 1.1884 + } 1.1885 + 1.1886 + return (writer.error() == NULL) ? 0 : -1; 1.1887 +} 1.1888 + 1.1889 +// stop timer (if still active), and free any error string we might be holding 1.1890 +HeapDumper::~HeapDumper() { 1.1891 + if (timer()->is_active()) { 1.1892 + timer()->stop(); 1.1893 + } 1.1894 + set_error(NULL); 1.1895 +} 1.1896 + 1.1897 + 1.1898 +// returns the error string (resource allocated), or NULL 1.1899 +char* HeapDumper::error_as_C_string() const { 1.1900 + if (error() != NULL) { 1.1901 + char* str = NEW_RESOURCE_ARRAY(char, strlen(error())+1); 1.1902 + strcpy(str, error()); 1.1903 + return str; 1.1904 + } else { 1.1905 + return NULL; 1.1906 + } 1.1907 +} 1.1908 + 1.1909 +// set the error string 1.1910 +void HeapDumper::set_error(char* error) { 1.1911 + if (_error != NULL) { 1.1912 + os::free(_error); 1.1913 + } 1.1914 + if (error == NULL) { 1.1915 + _error = NULL; 1.1916 + } else { 1.1917 + _error = os::strdup(error); 1.1918 + assert(_error != NULL, "allocation failure"); 1.1919 + } 1.1920 +} 1.1921 + 1.1922 +// Called by out-of-memory error reporting by a single Java thread 1.1923 +// outside of a JVM safepoint 1.1924 +void HeapDumper::dump_heap_from_oome() { 1.1925 + HeapDumper::dump_heap(true); 1.1926 +} 1.1927 + 1.1928 +// Called by error reporting by a single Java thread outside of a JVM safepoint, 1.1929 +// or by heap dumping by the VM thread during a (GC) safepoint. Thus, these various 1.1930 +// callers are strictly serialized and guaranteed not to interfere below. For more 1.1931 +// general use, however, this method will need modification to prevent 1.1932 +// inteference when updating the static variables base_path and dump_file_seq below. 1.1933 +void HeapDumper::dump_heap() { 1.1934 + HeapDumper::dump_heap(false); 1.1935 +} 1.1936 + 1.1937 +void HeapDumper::dump_heap(bool oome) { 1.1938 + static char base_path[JVM_MAXPATHLEN] = {'\0'}; 1.1939 + static uint dump_file_seq = 0; 1.1940 + char* my_path; 1.1941 + const int max_digit_chars = 20; 1.1942 + 1.1943 + const char* dump_file_name = "java_pid"; 1.1944 + const char* dump_file_ext = ".hprof"; 1.1945 + 1.1946 + // The dump file defaults to java_pid<pid>.hprof in the current working 1.1947 + // directory. HeapDumpPath=<file> can be used to specify an alternative 1.1948 + // dump file name or a directory where dump file is created. 1.1949 + if (dump_file_seq == 0) { // first time in, we initialize base_path 1.1950 + // Calculate potentially longest base path and check if we have enough 1.1951 + // allocated statically. 1.1952 + const size_t total_length = 1.1953 + (HeapDumpPath == NULL ? 0 : strlen(HeapDumpPath)) + 1.1954 + strlen(os::file_separator()) + max_digit_chars + 1.1955 + strlen(dump_file_name) + strlen(dump_file_ext) + 1; 1.1956 + if (total_length > sizeof(base_path)) { 1.1957 + warning("Cannot create heap dump file. HeapDumpPath is too long."); 1.1958 + return; 1.1959 + } 1.1960 + 1.1961 + bool use_default_filename = true; 1.1962 + if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') { 1.1963 + // HeapDumpPath=<file> not specified 1.1964 + } else { 1.1965 + strncpy(base_path, HeapDumpPath, sizeof(base_path)); 1.1966 + // check if the path is a directory (must exist) 1.1967 + DIR* dir = os::opendir(base_path); 1.1968 + if (dir == NULL) { 1.1969 + use_default_filename = false; 1.1970 + } else { 1.1971 + // HeapDumpPath specified a directory. We append a file separator 1.1972 + // (if needed). 1.1973 + os::closedir(dir); 1.1974 + size_t fs_len = strlen(os::file_separator()); 1.1975 + if (strlen(base_path) >= fs_len) { 1.1976 + char* end = base_path; 1.1977 + end += (strlen(base_path) - fs_len); 1.1978 + if (strcmp(end, os::file_separator()) != 0) { 1.1979 + strcat(base_path, os::file_separator()); 1.1980 + } 1.1981 + } 1.1982 + } 1.1983 + } 1.1984 + // If HeapDumpPath wasn't a file name then we append the default name 1.1985 + if (use_default_filename) { 1.1986 + const size_t dlen = strlen(base_path); // if heap dump dir specified 1.1987 + jio_snprintf(&base_path[dlen], sizeof(base_path)-dlen, "%s%d%s", 1.1988 + dump_file_name, os::current_process_id(), dump_file_ext); 1.1989 + } 1.1990 + const size_t len = strlen(base_path) + 1; 1.1991 + my_path = (char*)os::malloc(len, mtInternal); 1.1992 + if (my_path == NULL) { 1.1993 + warning("Cannot create heap dump file. Out of system memory."); 1.1994 + return; 1.1995 + } 1.1996 + strncpy(my_path, base_path, len); 1.1997 + } else { 1.1998 + // Append a sequence number id for dumps following the first 1.1999 + const size_t len = strlen(base_path) + max_digit_chars + 2; // for '.' and \0 1.2000 + my_path = (char*)os::malloc(len, mtInternal); 1.2001 + if (my_path == NULL) { 1.2002 + warning("Cannot create heap dump file. Out of system memory."); 1.2003 + return; 1.2004 + } 1.2005 + jio_snprintf(my_path, len, "%s.%d", base_path, dump_file_seq); 1.2006 + } 1.2007 + dump_file_seq++; // increment seq number for next time we dump 1.2008 + 1.2009 + HeapDumper dumper(false /* no GC before heap dump */, 1.2010 + true /* send to tty */, 1.2011 + oome /* pass along out-of-memory-error flag */); 1.2012 + dumper.dump(my_path); 1.2013 + os::free(my_path); 1.2014 +}