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