src/share/vm/services/heapDumper.cpp

changeset 8317
ebd6745380b9
parent 6680
78bbf4d43a14
child 8420
b5c3e9670fa0
equal deleted inserted replaced
8316:626f594dffa6 8317:ebd6745380b9
374 enum { 374 enum {
375 io_buffer_size = 8*M 375 io_buffer_size = 8*M
376 }; 376 };
377 377
378 int _fd; // file descriptor (-1 if dump file not open) 378 int _fd; // file descriptor (-1 if dump file not open)
379 jlong _bytes_written; // number of byte written to dump file 379 julong _bytes_written; // number of byte written to dump file
380 380
381 char* _buffer; // internal buffer 381 char* _buffer; // internal buffer
382 int _size; 382 size_t _size;
383 int _pos; 383 size_t _pos;
384 384
385 char* _error; // error message when I/O fails 385 char* _error; // error message when I/O fails
386 386
387 void set_file_descriptor(int fd) { _fd = fd; } 387 void set_file_descriptor(int fd) { _fd = fd; }
388 int file_descriptor() const { return _fd; } 388 int file_descriptor() const { return _fd; }
389 389
390 char* buffer() const { return _buffer; } 390 char* buffer() const { return _buffer; }
391 int buffer_size() const { return _size; } 391 size_t buffer_size() const { return _size; }
392 int position() const { return _pos; } 392 size_t position() const { return _pos; }
393 void set_position(int pos) { _pos = pos; } 393 void set_position(size_t pos) { _pos = pos; }
394 394
395 void set_error(const char* error) { _error = (char*)os::strdup(error); } 395 void set_error(const char* error) { _error = (char*)os::strdup(error); }
396 396
397 // all I/O go through this function 397 // all I/O go through this function
398 void write_internal(void* s, int len); 398 void write_internal(void* s, size_t len);
399 399
400 public: 400 public:
401 DumpWriter(const char* path); 401 DumpWriter(const char* path);
402 ~DumpWriter(); 402 ~DumpWriter();
403 403
404 void close(); 404 void close();
405 bool is_open() const { return file_descriptor() >= 0; } 405 bool is_open() const { return file_descriptor() >= 0; }
406 void flush(); 406 void flush();
407 407
408 // total number of bytes written to the disk 408 // total number of bytes written to the disk
409 jlong bytes_written() const { return _bytes_written; } 409 julong bytes_written() const { return _bytes_written; }
410 410
411 // adjust the number of bytes written to disk (used to keep the count 411 // adjust the number of bytes written to disk (used to keep the count
412 // of the number of bytes written in case of rewrites) 412 // of the number of bytes written in case of rewrites)
413 void adjust_bytes_written(jlong n) { _bytes_written += n; } 413 void adjust_bytes_written(jlong n) { _bytes_written += n; }
414 414
415 // number of (buffered) bytes as yet unwritten to the dump file 415 // number of (buffered) bytes as yet unwritten to the dump file
416 jlong bytes_unwritten() const { return (jlong)position(); } 416 size_t bytes_unwritten() const { return position(); }
417 417
418 char* error() const { return _error; } 418 char* error() const { return _error; }
419 419
420 jlong current_offset(); 420 jlong current_offset();
421 void seek_to_offset(jlong pos); 421 void seek_to_offset(jlong pos);
422 422
423 // writer functions 423 // writer functions
424 void write_raw(void* s, int len); 424 void write_raw(void* s, size_t len);
425 void write_u1(u1 x) { write_raw((void*)&x, 1); } 425 void write_u1(u1 x) { write_raw((void*)&x, 1); }
426 void write_u2(u2 x); 426 void write_u2(u2 x);
427 void write_u4(u4 x); 427 void write_u4(u4 x);
428 void write_u8(u8 x); 428 void write_u8(u8 x);
429 void write_objectID(oop o); 429 void write_objectID(oop o);
466 // closes dump file (if open) 466 // closes dump file (if open)
467 void DumpWriter::close() { 467 void DumpWriter::close() {
468 // flush and close dump file 468 // flush and close dump file
469 if (is_open()) { 469 if (is_open()) {
470 flush(); 470 flush();
471 ::close(file_descriptor()); 471 os::close(file_descriptor());
472 set_file_descriptor(-1); 472 set_file_descriptor(-1);
473 } 473 }
474 } 474 }
475 475
476 // write directly to the file 476 // write directly to the file
477 void DumpWriter::write_internal(void* s, int len) { 477 void DumpWriter::write_internal(void* s, size_t len) {
478 if (is_open()) { 478 if (is_open()) {
479 int n = ::write(file_descriptor(), s, len); 479 const char* pos = (char*)s;
480 if (n > 0) { 480 ssize_t n = 0;
481 while (len > 0) {
482 uint tmp = (uint)MIN2(len, (size_t)UINT_MAX);
483 n = os::write(file_descriptor(), pos, tmp);
484
485 if (n < 0) {
486 // EINTR cannot happen here, os::write will take care of that
487 set_error(strerror(errno));
488 os::close(file_descriptor());
489 set_file_descriptor(-1);
490 return;
491 }
492
481 _bytes_written += n; 493 _bytes_written += n;
482 } 494 pos += n;
483 if (n != len) { 495 len -= n;
484 if (n < 0) {
485 set_error(strerror(errno));
486 } else {
487 set_error("file size limit");
488 }
489 ::close(file_descriptor());
490 set_file_descriptor(-1);
491 } 496 }
492 } 497 }
493 } 498 }
494 499
495 // write raw bytes 500 // write raw bytes
496 void DumpWriter::write_raw(void* s, int len) { 501 void DumpWriter::write_raw(void* s, size_t len) {
497 if (is_open()) { 502 if (is_open()) {
498 // flush buffer to make toom 503 // flush buffer to make room
499 if ((position()+ len) >= buffer_size()) { 504 if ((position() + len) >= buffer_size()) {
500 flush(); 505 flush();
501 } 506 }
502 507
503 // buffer not available or too big to buffer it 508 // buffer not available or too big to buffer it
504 if ((buffer() == NULL) || (len >= buffer_size())) { 509 if ((buffer() == NULL) || (len >= buffer_size())) {
517 write_internal(buffer(), position()); 522 write_internal(buffer(), position());
518 set_position(0); 523 set_position(0);
519 } 524 }
520 } 525 }
521 526
522
523 jlong DumpWriter::current_offset() { 527 jlong DumpWriter::current_offset() {
524 if (is_open()) { 528 if (is_open()) {
525 // the offset is the file offset plus whatever we have buffered 529 // the offset is the file offset plus whatever we have buffered
526 jlong offset = os::current_file_offset(file_descriptor()); 530 jlong offset = os::current_file_offset(file_descriptor());
527 assert(offset >= 0, "lseek failed"); 531 assert(offset >= 0, "lseek failed");
528 return offset + (jlong)position(); 532 return offset + position();
529 } else { 533 } else {
530 return (jlong)-1; 534 return (jlong)-1;
531 } 535 }
532 } 536 }
533 537
772 // returns the size of the instance of the given class 776 // returns the size of the instance of the given class
773 u4 DumperSupport::instance_size(Klass* k) { 777 u4 DumperSupport::instance_size(Klass* k) {
774 HandleMark hm; 778 HandleMark hm;
775 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); 779 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k);
776 780
777 int size = 0; 781 u4 size = 0;
778 782
779 for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { 783 for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) {
780 if (!fld.access_flags().is_static()) { 784 if (!fld.access_flags().is_static()) {
781 Symbol* sig = fld.signature(); 785 Symbol* sig = fld.signature();
782 switch (sig->byte_at(0)) { 786 switch (sig->byte_at(0)) {
797 801
798 default : ShouldNotReachHere(); 802 default : ShouldNotReachHere();
799 } 803 }
800 } 804 }
801 } 805 }
802 return (u4)size; 806 return size;
803 } 807 }
804 808
805 // dumps static fields of the given class 809 // dumps static fields of the given class
806 void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { 810 void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) {
807 HandleMark hm; 811 HandleMark hm;
1029 if (array->length() == 0) { 1033 if (array->length() == 0) {
1030 return; 1034 return;
1031 } 1035 }
1032 1036
1033 // If the byte ordering is big endian then we can copy most types directly 1037 // If the byte ordering is big endian then we can copy most types directly
1034 int length_in_bytes = array->length() * type2aelembytes(type); 1038 u4 length_in_bytes = (u4)array->length() * type2aelembytes(type);
1035 assert(length_in_bytes > 0, "nothing to copy");
1036 1039
1037 switch (type) { 1040 switch (type) {
1038 case T_INT : { 1041 case T_INT : {
1039 if (Bytes::is_Java_byte_ordering_different()) { 1042 if (Bytes::is_Java_byte_ordering_different()) {
1040 WRITE_ARRAY(array, int, u4); 1043 WRITE_ARRAY(array, int, u4);
1283 if (!java_lang_Class::is_primitive(o)) { 1286 if (!java_lang_Class::is_primitive(o)) {
1284 return; 1287 return;
1285 } 1288 }
1286 } 1289 }
1287 1290
1288 // create a HPROF_GC_INSTANCE record for each object
1289 if (o->is_instance()) { 1291 if (o->is_instance()) {
1292 // create a HPROF_GC_INSTANCE record for each object
1290 DumperSupport::dump_instance(writer(), o); 1293 DumperSupport::dump_instance(writer(), o);
1291 mark_end_of_record(); 1294 mark_end_of_record();
1292 } else { 1295 } else if (o->is_objArray()) {
1293 // create a HPROF_GC_OBJ_ARRAY_DUMP record for each object array 1296 // create a HPROF_GC_OBJ_ARRAY_DUMP record for each object array
1294 if (o->is_objArray()) { 1297 DumperSupport::dump_object_array(writer(), objArrayOop(o));
1295 DumperSupport::dump_object_array(writer(), objArrayOop(o)); 1298 mark_end_of_record();
1296 mark_end_of_record(); 1299 } else if (o->is_typeArray()) {
1297 } else { 1300 // create a HPROF_GC_PRIM_ARRAY_DUMP record for each type array
1298 // create a HPROF_GC_PRIM_ARRAY_DUMP record for each type array 1301 DumperSupport::dump_prim_array(writer(), typeArrayOop(o));
1299 if (o->is_typeArray()) { 1302 mark_end_of_record();
1300 DumperSupport::dump_prim_array(writer(), typeArrayOop(o));
1301 mark_end_of_record();
1302 }
1303 }
1304 } 1303 }
1305 } 1304 }
1306 1305
1307 // The VM operation that performs the heap dump 1306 // The VM operation that performs the heap dump
1308 class VM_HeapDumper : public VM_GC_Operation { 1307 class VM_HeapDumper : public VM_GC_Operation {
1446 void VM_HeapDumper::write_current_dump_record_length() { 1445 void VM_HeapDumper::write_current_dump_record_length() {
1447 if (writer()->is_open()) { 1446 if (writer()->is_open()) {
1448 assert(dump_start() >= 0, "no dump start recorded"); 1447 assert(dump_start() >= 0, "no dump start recorded");
1449 1448
1450 // calculate the size of the dump record 1449 // calculate the size of the dump record
1451 jlong dump_end = writer()->current_offset(); 1450 julong dump_end = writer()->current_offset();
1452 jlong dump_len = (dump_end - dump_start() - 4); 1451 julong dump_len = (dump_end - dump_start() - 4);
1453 1452
1454 // record length must fit in a u4 1453 // record length must fit in a u4
1455 if (dump_len > (jlong)(4L*(jlong)G)) { 1454 if (dump_len > max_juint) {
1456 warning("record is too large"); 1455 warning("record is too large");
1457 } 1456 }
1458 1457
1459 // seek to the dump start and fix-up the length 1458 // seek to the dump start and fix-up the length
1460 writer()->seek_to_offset(dump_start()); 1459 writer()->seek_to_offset(dump_start());
1461 writer()->write_u4((u4)dump_len); 1460 writer()->write_u4((u4)dump_len);
1462 1461
1463 // adjust the total size written to keep the bytes written correct. 1462 // adjust the total size written to keep the bytes written correct.
1464 writer()->adjust_bytes_written(-((long) sizeof(u4))); 1463 writer()->adjust_bytes_written(-((jlong) sizeof(u4)));
1465 1464
1466 // seek to dump end so we can continue 1465 // seek to dump end so we can continue
1467 writer()->seek_to_offset(dump_end); 1466 writer()->seek_to_offset(dump_end);
1468 1467
1469 // no current dump record 1468 // no current dump record
1475 // new segment. 1474 // new segment.
1476 void VM_HeapDumper::check_segment_length() { 1475 void VM_HeapDumper::check_segment_length() {
1477 if (writer()->is_open()) { 1476 if (writer()->is_open()) {
1478 if (is_segmented_dump()) { 1477 if (is_segmented_dump()) {
1479 // don't use current_offset that would be too expensive on a per record basis 1478 // don't use current_offset that would be too expensive on a per record basis
1480 jlong dump_end = writer()->bytes_written() + writer()->bytes_unwritten(); 1479 julong dump_end = writer()->bytes_written() + writer()->bytes_unwritten();
1481 assert(dump_end == writer()->current_offset(), "checking"); 1480 assert(dump_end == (julong)writer()->current_offset(), "checking");
1482 jlong dump_len = (dump_end - dump_start() - 4); 1481 julong dump_len = (dump_end - dump_start() - 4);
1483 assert(dump_len >= 0 && dump_len <= max_juint, "bad dump length"); 1482 assert(dump_len <= max_juint, "bad dump length");
1484 1483
1485 if (dump_len > (jlong)HeapDumpSegmentSize) { 1484 if (dump_len > HeapDumpSegmentSize) {
1486 write_current_dump_record_length(); 1485 write_current_dump_record_length();
1487 write_dump_header(); 1486 write_dump_header();
1488 } 1487 }
1489 } 1488 }
1490 } 1489 }
1866 1865
1867 // print message in interactive case 1866 // print message in interactive case
1868 if (print_to_tty()) { 1867 if (print_to_tty()) {
1869 timer()->stop(); 1868 timer()->stop();
1870 if (error() == NULL) { 1869 if (error() == NULL) {
1871 char msg[256]; 1870 tty->print_cr("Heap dump file created [" JULONG_FORMAT " bytes in %3.3f secs]",
1872 sprintf(msg, "Heap dump file created [%s bytes in %3.3f secs]", 1871 writer.bytes_written(), timer()->seconds());
1873 JLONG_FORMAT, timer()->seconds());
1874 PRAGMA_DIAG_PUSH
1875 PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
1876 tty->print_cr(msg, writer.bytes_written());
1877 PRAGMA_DIAG_POP
1878 } else { 1872 } else {
1879 tty->print_cr("Dump file is incomplete: %s", writer.error()); 1873 tty->print_cr("Dump file is incomplete: %s", writer.error());
1880 } 1874 }
1881 } 1875 }
1882 1876

mercurial