1301 } |
1300 } |
1302 |
1301 |
1303 // The VM operation that performs the heap dump |
1302 // The VM operation that performs the heap dump |
1304 class VM_HeapDumper : public VM_GC_Operation { |
1303 class VM_HeapDumper : public VM_GC_Operation { |
1305 private: |
1304 private: |
1306 DumpWriter* _writer; |
1305 static VM_HeapDumper* _global_dumper; |
|
1306 static DumpWriter* _global_writer; |
|
1307 DumpWriter* _local_writer; |
1307 bool _gc_before_heap_dump; |
1308 bool _gc_before_heap_dump; |
1308 bool _is_segmented_dump; |
1309 bool _is_segmented_dump; |
1309 jlong _dump_start; |
1310 jlong _dump_start; |
1310 GrowableArray<Klass*>* _klass_map; |
1311 GrowableArray<Klass*>* _klass_map; |
1311 ThreadStackTrace** _stack_traces; |
1312 ThreadStackTrace** _stack_traces; |
1312 int _num_threads; |
1313 int _num_threads; |
1313 |
1314 |
1314 // accessors |
1315 // accessors and setters |
1315 DumpWriter* writer() const { return _writer; } |
1316 static VM_HeapDumper* dumper() { assert(_global_dumper != NULL, "Error"); return _global_dumper; } |
|
1317 static DumpWriter* writer() { assert(_global_writer != NULL, "Error"); return _global_writer; } |
|
1318 void set_global_dumper() { |
|
1319 assert(_global_dumper == NULL, "Error"); |
|
1320 _global_dumper = this; |
|
1321 } |
|
1322 void set_global_writer() { |
|
1323 assert(_global_writer == NULL, "Error"); |
|
1324 _global_writer = _local_writer; |
|
1325 } |
|
1326 void clear_global_dumper() { _global_dumper = NULL; } |
|
1327 void clear_global_writer() { _global_writer = NULL; } |
|
1328 |
1316 bool is_segmented_dump() const { return _is_segmented_dump; } |
1329 bool is_segmented_dump() const { return _is_segmented_dump; } |
1317 void set_segmented_dump() { _is_segmented_dump = true; } |
1330 void set_segmented_dump() { _is_segmented_dump = true; } |
1318 jlong dump_start() const { return _dump_start; } |
1331 jlong dump_start() const { return _dump_start; } |
1319 void set_dump_start(jlong pos); |
1332 void set_dump_start(jlong pos); |
1320 |
1333 |
1355 public: |
1368 public: |
1356 VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump) : |
1369 VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump) : |
1357 VM_GC_Operation(0 /* total collections, dummy, ignored */, |
1370 VM_GC_Operation(0 /* total collections, dummy, ignored */, |
1358 0 /* total full collections, dummy, ignored */, |
1371 0 /* total full collections, dummy, ignored */, |
1359 gc_before_heap_dump) { |
1372 gc_before_heap_dump) { |
1360 _writer = writer; |
1373 _local_writer = writer; |
1361 _gc_before_heap_dump = gc_before_heap_dump; |
1374 _gc_before_heap_dump = gc_before_heap_dump; |
1362 _is_segmented_dump = false; |
1375 _is_segmented_dump = false; |
1363 _dump_start = (jlong)-1; |
1376 _dump_start = (jlong)-1; |
1364 _klass_map = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, true); |
1377 _klass_map = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, true); |
1365 _stack_traces = NULL; |
1378 _stack_traces = NULL; |
1477 // writes a HPROF_LOAD_CLASS record for the class (and each of its |
1493 // writes a HPROF_LOAD_CLASS record for the class (and each of its |
1478 // array classes) |
1494 // array classes) |
1479 void VM_HeapDumper::do_load_class(klassOop k) { |
1495 void VM_HeapDumper::do_load_class(klassOop k) { |
1480 static u4 class_serial_num = 0; |
1496 static u4 class_serial_num = 0; |
1481 |
1497 |
1482 VM_HeapDumper* dumper = ((VM_HeapDumper*)VMThread::vm_operation()); |
|
1483 DumpWriter* writer = dumper->writer(); |
|
1484 |
|
1485 // len of HPROF_LOAD_CLASS record |
1498 // len of HPROF_LOAD_CLASS record |
1486 u4 remaining = 2*oopSize + 2*sizeof(u4); |
1499 u4 remaining = 2*oopSize + 2*sizeof(u4); |
1487 |
1500 |
1488 // write a HPROF_LOAD_CLASS for the class and each array class |
1501 // write a HPROF_LOAD_CLASS for the class and each array class |
1489 do { |
1502 do { |
1490 DumperSupport::write_header(writer, HPROF_LOAD_CLASS, remaining); |
1503 DumperSupport::write_header(writer(), HPROF_LOAD_CLASS, remaining); |
1491 |
1504 |
1492 // class serial number is just a number |
1505 // class serial number is just a number |
1493 writer->write_u4(++class_serial_num); |
1506 writer()->write_u4(++class_serial_num); |
1494 |
1507 |
1495 // class ID |
1508 // class ID |
1496 Klass* klass = Klass::cast(k); |
1509 Klass* klass = Klass::cast(k); |
1497 writer->write_classID(klass); |
1510 writer()->write_classID(klass); |
1498 |
1511 |
1499 // add the klassOop and class serial number pair |
1512 // add the klassOop and class serial number pair |
1500 dumper->add_class_serial_number(klass, class_serial_num); |
1513 dumper()->add_class_serial_number(klass, class_serial_num); |
1501 |
1514 |
1502 writer->write_u4(STACK_TRACE_ID); |
1515 writer()->write_u4(STACK_TRACE_ID); |
1503 |
1516 |
1504 // class name ID |
1517 // class name ID |
1505 symbolOop name = klass->name(); |
1518 symbolOop name = klass->name(); |
1506 writer->write_objectID(name); |
1519 writer()->write_objectID(name); |
1507 |
1520 |
1508 // write a LOAD_CLASS record for the array type (if it exists) |
1521 // write a LOAD_CLASS record for the array type (if it exists) |
1509 k = klass->array_klass_or_null(); |
1522 k = klass->array_klass_or_null(); |
1510 } while (k != NULL); |
1523 } while (k != NULL); |
1511 } |
1524 } |
1512 |
1525 |
1513 // writes a HPROF_GC_CLASS_DUMP record for the given class |
1526 // writes a HPROF_GC_CLASS_DUMP record for the given class |
1514 void VM_HeapDumper::do_class_dump(klassOop k) { |
1527 void VM_HeapDumper::do_class_dump(klassOop k) { |
1515 VM_HeapDumper* dumper = ((VM_HeapDumper*)VMThread::vm_operation()); |
1528 DumperSupport::dump_class_and_array_classes(writer(), k); |
1516 DumpWriter* writer = dumper->writer(); |
|
1517 DumperSupport::dump_class_and_array_classes(writer, k); |
|
1518 } |
1529 } |
1519 |
1530 |
1520 // writes a HPROF_GC_CLASS_DUMP records for a given basic type |
1531 // writes a HPROF_GC_CLASS_DUMP records for a given basic type |
1521 // array (and each multi-dimensional array too) |
1532 // array (and each multi-dimensional array too) |
1522 void VM_HeapDumper::do_basic_type_array_class_dump(klassOop k) { |
1533 void VM_HeapDumper::do_basic_type_array_class_dump(klassOop k) { |
1523 VM_HeapDumper* dumper = ((VM_HeapDumper*)VMThread::vm_operation()); |
1534 DumperSupport::dump_basic_type_array_class(writer(), k); |
1524 DumpWriter* writer = dumper->writer(); |
|
1525 DumperSupport::dump_basic_type_array_class(writer, k); |
|
1526 } |
1535 } |
1527 |
1536 |
1528 // Walk the stack of the given thread. |
1537 // Walk the stack of the given thread. |
1529 // Dumps a HPROF_GC_ROOT_JAVA_FRAME record for each local |
1538 // Dumps a HPROF_GC_ROOT_JAVA_FRAME record for each local |
1530 // Dumps a HPROF_GC_ROOT_JNI_LOCAL record for each JNI local |
1539 // Dumps a HPROF_GC_ROOT_JNI_LOCAL record for each JNI local |
1656 } else { |
1665 } else { |
1657 // make the heap parsable (no need to retire TLABs) |
1666 // make the heap parsable (no need to retire TLABs) |
1658 ch->ensure_parsability(false); |
1667 ch->ensure_parsability(false); |
1659 } |
1668 } |
1660 |
1669 |
|
1670 // At this point we should be the only dumper active, so |
|
1671 // the following should be safe. |
|
1672 set_global_dumper(); |
|
1673 set_global_writer(); |
|
1674 |
1661 // Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1 |
1675 // Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1 |
1662 size_t used = ch->used(); |
1676 size_t used = ch->used(); |
1663 const char* header; |
1677 const char* header; |
1664 if (used > (size_t)SegmentedHeapDumpThreshold) { |
1678 if (used > (size_t)SegmentedHeapDumpThreshold) { |
1665 set_segmented_dump(); |
1679 set_segmented_dump(); |
1666 header = "JAVA PROFILE 1.0.2"; |
1680 header = "JAVA PROFILE 1.0.2"; |
1667 } else { |
1681 } else { |
1668 header = "JAVA PROFILE 1.0.1"; |
1682 header = "JAVA PROFILE 1.0.1"; |
1669 } |
1683 } |
|
1684 |
1670 // header is few bytes long - no chance to overflow int |
1685 // header is few bytes long - no chance to overflow int |
1671 writer()->write_raw((void*)header, (int)strlen(header)); |
1686 writer()->write_raw((void*)header, (int)strlen(header)); |
1672 writer()->write_u1(0); // terminator |
1687 writer()->write_u1(0); // terminator |
1673 writer()->write_u4(oopSize); |
1688 writer()->write_u4(oopSize); |
1674 writer()->write_u8(os::javaTimeMillis()); |
1689 writer()->write_u8(os::javaTimeMillis()); |
1843 _error = os::strdup(error); |
1867 _error = os::strdup(error); |
1844 assert(_error != NULL, "allocation failure"); |
1868 assert(_error != NULL, "allocation failure"); |
1845 } |
1869 } |
1846 } |
1870 } |
1847 |
1871 |
1848 |
1872 // Called by error reporting by a single Java thread outside of a JVM safepoint, |
1849 // Called by error reporting |
1873 // or by heap dumping by the VM thread during a (GC) safepoint. Thus, these various |
|
1874 // callers are strictly serialized and guaranteed not to interfere below. For more |
|
1875 // general use, however, this method will need modification to prevent |
|
1876 // inteference when updating the static variables base_path and dump_file_seq below. |
1850 void HeapDumper::dump_heap() { |
1877 void HeapDumper::dump_heap() { |
1851 static char path[JVM_MAXPATHLEN]; |
1878 static char base_path[JVM_MAXPATHLEN] = {'\0'}; |
|
1879 static uint dump_file_seq = 0; |
|
1880 char my_path[JVM_MAXPATHLEN] = {'\0'}; |
1852 |
1881 |
1853 // The dump file defaults to java_pid<pid>.hprof in the current working |
1882 // The dump file defaults to java_pid<pid>.hprof in the current working |
1854 // directory. HeapDumpPath=<file> can be used to specify an alternative |
1883 // directory. HeapDumpPath=<file> can be used to specify an alternative |
1855 // dump file name or a directory where dump file is created. |
1884 // dump file name or a directory where dump file is created. |
1856 bool use_default_filename = true; |
1885 if (dump_file_seq == 0) { // first time in, we initialize base_path |
1857 if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') { |
1886 bool use_default_filename = true; |
1858 path[0] = '\0'; // HeapDumpPath=<file> not specified |
1887 if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') { |
1859 } else { |
1888 // HeapDumpPath=<file> not specified |
1860 assert(strlen(HeapDumpPath) < sizeof(path), "HeapDumpPath too long"); |
|
1861 strcpy(path, HeapDumpPath); |
|
1862 // check if the path is a directory (must exist) |
|
1863 DIR* dir = os::opendir(path); |
|
1864 if (dir == NULL) { |
|
1865 use_default_filename = false; |
|
1866 } else { |
1889 } else { |
1867 // HeapDumpPath specified a directory. We append a file separator |
1890 assert(strlen(HeapDumpPath) < sizeof(base_path), "HeapDumpPath too long"); |
1868 // (if needed). |
1891 strcpy(base_path, HeapDumpPath); |
1869 os::closedir(dir); |
1892 // check if the path is a directory (must exist) |
1870 size_t fs_len = strlen(os::file_separator()); |
1893 DIR* dir = os::opendir(base_path); |
1871 if (strlen(path) >= fs_len) { |
1894 if (dir == NULL) { |
1872 char* end = path; |
1895 use_default_filename = false; |
1873 end += (strlen(path) - fs_len); |
1896 } else { |
1874 if (strcmp(end, os::file_separator()) != 0) { |
1897 // HeapDumpPath specified a directory. We append a file separator |
1875 assert(strlen(path) + strlen(os::file_separator()) < sizeof(path), |
1898 // (if needed). |
1876 "HeapDumpPath too long"); |
1899 os::closedir(dir); |
1877 strcat(path, os::file_separator()); |
1900 size_t fs_len = strlen(os::file_separator()); |
|
1901 if (strlen(base_path) >= fs_len) { |
|
1902 char* end = base_path; |
|
1903 end += (strlen(base_path) - fs_len); |
|
1904 if (strcmp(end, os::file_separator()) != 0) { |
|
1905 assert(strlen(base_path) + strlen(os::file_separator()) < sizeof(base_path), |
|
1906 "HeapDumpPath too long"); |
|
1907 strcat(base_path, os::file_separator()); |
|
1908 } |
1878 } |
1909 } |
1879 } |
1910 } |
1880 } |
1911 } |
1881 } |
1912 // If HeapDumpPath wasn't a file name then we append the default name |
1882 // If HeapDumpPath wasn't a file name then we append the default name |
1913 if (use_default_filename) { |
1883 if (use_default_filename) { |
1914 char fn[32]; |
1884 char fn[32]; |
1915 sprintf(fn, "java_pid%d", os::current_process_id()); |
1885 sprintf(fn, "java_pid%d.hprof", os::current_process_id()); |
1916 assert(strlen(base_path) + strlen(fn) < sizeof(base_path), "HeapDumpPath too long"); |
1886 assert(strlen(path) + strlen(fn) < sizeof(path), "HeapDumpPath too long"); |
1917 strcat(base_path, fn); |
1887 strcat(path, fn); |
1918 } |
1888 } |
1919 assert(strlen(base_path) < sizeof(my_path), "Buffer too small"); |
|
1920 strcpy(my_path, base_path); |
|
1921 } else { |
|
1922 // Append a sequence number id for dumps following the first |
|
1923 char fn[33]; |
|
1924 sprintf(fn, ".%d", dump_file_seq); |
|
1925 assert(strlen(base_path) + strlen(fn) < sizeof(my_path), "HeapDumpPath too long"); |
|
1926 strcpy(my_path, base_path); |
|
1927 strcat(my_path, fn); |
|
1928 } |
|
1929 dump_file_seq++; // increment seq number for next time we dump |
|
1930 assert(strlen(".hprof") + strlen(my_path) < sizeof(my_path), "HeapDumpPath too long"); |
|
1931 strcat(my_path, ".hprof"); |
1889 |
1932 |
1890 HeapDumper dumper(false /* no GC before heap dump */, |
1933 HeapDumper dumper(false /* no GC before heap dump */, |
1891 true /* send to tty */); |
1934 true /* send to tty */); |
1892 dumper.dump(path); |
1935 dumper.dump(my_path); |
1893 } |
1936 } |