Mercurial > hg > graal-jvmci-8
comparison src/share/vm/services/heapDumper.cpp @ 23974:f13e777eb255
Merge with jdk8u111-b14
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Wed, 16 Nov 2016 12:32:54 -0800 |
parents | 52b4284cb496 b5c3e9670fa0 |
children |
comparison
equal
deleted
inserted
replaced
23792:3953f8820df8 | 23974:f13e777eb255 |
---|---|
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); |
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 _bytes_written += n; | 481 while (len > 0) { |
482 } | 482 uint tmp = (uint)MIN2(len, (size_t)UINT_MAX); |
483 if (n != len) { | 483 n = ::write(file_descriptor(), pos, tmp); |
484 | |
484 if (n < 0) { | 485 if (n < 0) { |
485 set_error(strerror(errno)); | 486 set_error(strerror(errno)); |
486 } else { | 487 ::close(file_descriptor()); |
487 set_error("file size limit"); | 488 set_file_descriptor(-1); |
489 return; | |
488 } | 490 } |
489 ::close(file_descriptor()); | 491 |
490 set_file_descriptor(-1); | 492 _bytes_written += n; |
493 pos += n; | |
494 len -= n; | |
491 } | 495 } |
492 } | 496 } |
493 } | 497 } |
494 | 498 |
495 // write raw bytes | 499 // write raw bytes |
496 void DumpWriter::write_raw(void* s, int len) { | 500 void DumpWriter::write_raw(void* s, size_t len) { |
497 if (is_open()) { | 501 if (is_open()) { |
498 // flush buffer to make toom | 502 // flush buffer to make room |
499 if ((position()+ len) >= buffer_size()) { | 503 if ((position() + len) >= buffer_size()) { |
500 flush(); | 504 flush(); |
501 } | 505 } |
502 | 506 |
503 // buffer not available or too big to buffer it | 507 // buffer not available or too big to buffer it |
504 if ((buffer() == NULL) || (len >= buffer_size())) { | 508 if ((buffer() == NULL) || (len >= buffer_size())) { |
517 write_internal(buffer(), position()); | 521 write_internal(buffer(), position()); |
518 set_position(0); | 522 set_position(0); |
519 } | 523 } |
520 } | 524 } |
521 | 525 |
522 | |
523 jlong DumpWriter::current_offset() { | 526 jlong DumpWriter::current_offset() { |
524 if (is_open()) { | 527 if (is_open()) { |
525 // the offset is the file offset plus whatever we have buffered | 528 // the offset is the file offset plus whatever we have buffered |
526 jlong offset = os::current_file_offset(file_descriptor()); | 529 jlong offset = os::current_file_offset(file_descriptor()); |
527 assert(offset >= 0, "lseek failed"); | 530 assert(offset >= 0, "lseek failed"); |
528 return offset + (jlong)position(); | 531 return offset + position(); |
529 } else { | 532 } else { |
530 return (jlong)-1; | 533 return (jlong)-1; |
531 } | 534 } |
532 } | 535 } |
533 | 536 |
772 // returns the size of the instance of the given class | 775 // returns the size of the instance of the given class |
773 u4 DumperSupport::instance_size(Klass* k) { | 776 u4 DumperSupport::instance_size(Klass* k) { |
774 HandleMark hm; | 777 HandleMark hm; |
775 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); | 778 instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k); |
776 | 779 |
777 int size = 0; | 780 u4 size = 0; |
778 | 781 |
779 for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { | 782 for (FieldStream fld(ikh, false, false); !fld.eos(); fld.next()) { |
780 if (!fld.access_flags().is_static()) { | 783 if (!fld.access_flags().is_static()) { |
781 Symbol* sig = fld.signature(); | 784 Symbol* sig = fld.signature(); |
782 switch (sig->byte_at(0)) { | 785 switch (sig->byte_at(0)) { |
797 | 800 |
798 default : ShouldNotReachHere(); | 801 default : ShouldNotReachHere(); |
799 } | 802 } |
800 } | 803 } |
801 } | 804 } |
802 return (u4)size; | 805 return size; |
803 } | 806 } |
804 | 807 |
805 // dumps static fields of the given class | 808 // dumps static fields of the given class |
806 void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { | 809 void DumperSupport::dump_static_fields(DumpWriter* writer, Klass* k) { |
807 HandleMark hm; | 810 HandleMark hm; |
1029 if (array->length() == 0) { | 1032 if (array->length() == 0) { |
1030 return; | 1033 return; |
1031 } | 1034 } |
1032 | 1035 |
1033 // If the byte ordering is big endian then we can copy most types directly | 1036 // If the byte ordering is big endian then we can copy most types directly |
1034 int length_in_bytes = array->length() * type2aelembytes(type); | 1037 u4 length_in_bytes = (u4)array->length() * type2aelembytes(type); |
1035 assert(length_in_bytes > 0, "nothing to copy"); | |
1036 | 1038 |
1037 switch (type) { | 1039 switch (type) { |
1038 case T_INT : { | 1040 case T_INT : { |
1039 if (Bytes::is_Java_byte_ordering_different()) { | 1041 if (Bytes::is_Java_byte_ordering_different()) { |
1040 WRITE_ARRAY(array, int, u4); | 1042 WRITE_ARRAY(array, int, u4); |
1283 if (!java_lang_Class::is_primitive(o)) { | 1285 if (!java_lang_Class::is_primitive(o)) { |
1284 return; | 1286 return; |
1285 } | 1287 } |
1286 } | 1288 } |
1287 | 1289 |
1288 // create a HPROF_GC_INSTANCE record for each object | |
1289 if (o->is_instance()) { | 1290 if (o->is_instance()) { |
1291 // create a HPROF_GC_INSTANCE record for each object | |
1290 DumperSupport::dump_instance(writer(), o); | 1292 DumperSupport::dump_instance(writer(), o); |
1291 mark_end_of_record(); | 1293 mark_end_of_record(); |
1292 } else { | 1294 } else if (o->is_objArray()) { |
1293 // create a HPROF_GC_OBJ_ARRAY_DUMP record for each object array | 1295 // create a HPROF_GC_OBJ_ARRAY_DUMP record for each object array |
1294 if (o->is_objArray()) { | 1296 DumperSupport::dump_object_array(writer(), objArrayOop(o)); |
1295 DumperSupport::dump_object_array(writer(), objArrayOop(o)); | 1297 mark_end_of_record(); |
1296 mark_end_of_record(); | 1298 } else if (o->is_typeArray()) { |
1297 } else { | 1299 // 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 | 1300 DumperSupport::dump_prim_array(writer(), typeArrayOop(o)); |
1299 if (o->is_typeArray()) { | 1301 mark_end_of_record(); |
1300 DumperSupport::dump_prim_array(writer(), typeArrayOop(o)); | |
1301 mark_end_of_record(); | |
1302 } | |
1303 } | |
1304 } | 1302 } |
1305 } | 1303 } |
1306 | 1304 |
1307 // The VM operation that performs the heap dump | 1305 // The VM operation that performs the heap dump |
1308 class VM_HeapDumper : public VM_GC_Operation { | 1306 class VM_HeapDumper : public VM_GC_Operation { |
1446 void VM_HeapDumper::write_current_dump_record_length() { | 1444 void VM_HeapDumper::write_current_dump_record_length() { |
1447 if (writer()->is_open()) { | 1445 if (writer()->is_open()) { |
1448 assert(dump_start() >= 0, "no dump start recorded"); | 1446 assert(dump_start() >= 0, "no dump start recorded"); |
1449 | 1447 |
1450 // calculate the size of the dump record | 1448 // calculate the size of the dump record |
1451 jlong dump_end = writer()->current_offset(); | 1449 julong dump_end = writer()->current_offset(); |
1452 jlong dump_len = (dump_end - dump_start() - 4); | 1450 julong dump_len = (dump_end - dump_start() - 4); |
1453 | 1451 |
1454 // record length must fit in a u4 | 1452 // record length must fit in a u4 |
1455 if (dump_len > (jlong)(4L*(jlong)G)) { | 1453 if (dump_len > max_juint) { |
1456 warning("record is too large"); | 1454 warning("record is too large"); |
1457 } | 1455 } |
1458 | 1456 |
1459 // seek to the dump start and fix-up the length | 1457 // seek to the dump start and fix-up the length |
1460 writer()->seek_to_offset(dump_start()); | 1458 writer()->seek_to_offset(dump_start()); |
1461 writer()->write_u4((u4)dump_len); | 1459 writer()->write_u4((u4)dump_len); |
1462 | 1460 |
1463 // adjust the total size written to keep the bytes written correct. | 1461 // adjust the total size written to keep the bytes written correct. |
1464 writer()->adjust_bytes_written(-((long) sizeof(u4))); | 1462 writer()->adjust_bytes_written(-((jlong) sizeof(u4))); |
1465 | 1463 |
1466 // seek to dump end so we can continue | 1464 // seek to dump end so we can continue |
1467 writer()->seek_to_offset(dump_end); | 1465 writer()->seek_to_offset(dump_end); |
1468 | 1466 |
1469 // no current dump record | 1467 // no current dump record |
1475 // new segment. | 1473 // new segment. |
1476 void VM_HeapDumper::check_segment_length() { | 1474 void VM_HeapDumper::check_segment_length() { |
1477 if (writer()->is_open()) { | 1475 if (writer()->is_open()) { |
1478 if (is_segmented_dump()) { | 1476 if (is_segmented_dump()) { |
1479 // don't use current_offset that would be too expensive on a per record basis | 1477 // 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(); | 1478 julong dump_end = writer()->bytes_written() + writer()->bytes_unwritten(); |
1481 assert(dump_end == writer()->current_offset(), "checking"); | 1479 assert(dump_end == (julong)writer()->current_offset(), "checking"); |
1482 jlong dump_len = (dump_end - dump_start() - 4); | 1480 julong dump_len = (dump_end - dump_start() - 4); |
1483 assert(dump_len >= 0 && dump_len <= max_juint, "bad dump length"); | 1481 assert(dump_len <= max_juint, "bad dump length"); |
1484 | 1482 |
1485 if (dump_len > (jlong)HeapDumpSegmentSize) { | 1483 if (dump_len > HeapDumpSegmentSize) { |
1486 write_current_dump_record_length(); | 1484 write_current_dump_record_length(); |
1487 write_dump_header(); | 1485 write_dump_header(); |
1488 } | 1486 } |
1489 } | 1487 } |
1490 } | 1488 } |
1866 | 1864 |
1867 // print message in interactive case | 1865 // print message in interactive case |
1868 if (print_to_tty()) { | 1866 if (print_to_tty()) { |
1869 timer()->stop(); | 1867 timer()->stop(); |
1870 if (error() == NULL) { | 1868 if (error() == NULL) { |
1871 char msg[256]; | 1869 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]", | 1870 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 { | 1871 } else { |
1879 tty->print_cr("Dump file is incomplete: %s", writer.error()); | 1872 tty->print_cr("Dump file is incomplete: %s", writer.error()); |
1880 } | 1873 } |
1881 } | 1874 } |
1882 | 1875 |