hotspot/src/share/vm/services/heapDumper.cpp
// The VM operation that dumps the heap. The dump consists of the following // records: // // HPROF_HEADER // [HPROF_UTF8]* // [HPROF_LOAD_CLASS]* // [[HPROF_FRAME]|HPROF_TRACE] // [HPROF_GC_CLASS_DUMP]* // HPROF_HEAP_DUMP // // The HPROF_TRACE records represent the stack traces where the heap dump // is generated and a "dummy trace" record which does not include // any frames. The dummy trace record is used to be referenced as the // unknown object alloc site. // // The HPROF_HEAP_DUMP record has a length following by sub-records. To allow // the heap dump be generated in a single pass we remember the position of // the dump length and fix it up after all sub-records have been written. // To generate the sub-records we iterate over the heap, writing // HPROF_GC_INSTANCE_DUMP, HPROF_GC_OBJ_ARRAY_DUMP, and HPROF_GC_PRIM_ARRAY_DUMP // records as we go. Once that is done we write records for some of the GC // roots.
void VM_HeapDumper::doit() {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
HandleMark hm;
CollectedHeap* ch = Universe::heap();
{- -------------------------------------------
(1)
---------------------------------------- -}
if (_gc_before_heap_dump) {
ch->collect_as_vm_thread(GCCause::_heap_dump);
} else {
// make the heap parsable (no need to retire TLABs)
ch->ensure_parsability(false);
}
{- -------------------------------------------
(1)
---------------------------------------- -}
// At this point we should be the only dumper active, so
// the following should be safe.
set_global_dumper();
set_global_writer();
{- -------------------------------------------
(1) まずヘッダー部分を出力する.
---------------------------------------- -}
// Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1
size_t used = ch->used();
const char* header;
if (used > (size_t)SegmentedHeapDumpThreshold) {
set_segmented_dump();
header = "JAVA PROFILE 1.0.2";
} else {
header = "JAVA PROFILE 1.0.1";
}
// header is few bytes long - no chance to overflow int
writer()->write_raw((void*)header, (int)strlen(header));
writer()->write_u1(0); // terminator
writer()->write_u4(oopSize);
writer()->write_u8(os::javaTimeMillis());
{- -------------------------------------------
(1) SymbolTableDumper を使って, HPROF_UTF8 record を出力する.
---------------------------------------- -}
// HPROF_UTF8 records
SymbolTableDumper sym_dumper(writer());
SymbolTable::symbols_do(&sym_dumper);
{- -------------------------------------------
(1) HPROF_LOAD_CLASS record を出力する.
---------------------------------------- -}
// write HPROF_LOAD_CLASS records
SystemDictionary::classes_do(&do_load_class);
Universe::basic_type_classes_do(&do_load_class);
{- -------------------------------------------
(1) #TODO (というか, 既に全部コメントが入ってる...)
---------------------------------------- -}
// write HPROF_FRAME and HPROF_TRACE records
// this must be called after _klass_map is built when iterating the classes above.
dump_stack_traces();
// write HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT
write_dump_header();
// Writes HPROF_GC_CLASS_DUMP records
SystemDictionary::classes_do(&do_class_dump);
Universe::basic_type_classes_do(&do_basic_type_array_class_dump);
check_segment_length();
// writes HPROF_GC_INSTANCE_DUMP records.
// After each sub-record is written check_segment_length will be invoked. When
// generated a segmented heap dump this allows us to check if the current
// segment exceeds a threshold and if so, then a new segment is started.
// The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk
// of the heap dump.
HeapObjectDumper obj_dumper(this, writer());
Universe::heap()->safe_object_iterate(&obj_dumper);
// HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals
do_threads();
check_segment_length();
// HPROF_GC_ROOT_MONITOR_USED
MonitorUsedDumper mon_dumper(writer());
ObjectSynchronizer::oops_do(&mon_dumper);
check_segment_length();
// HPROF_GC_ROOT_JNI_GLOBAL
JNIGlobalsDumper jni_dumper(writer());
JNIHandles::oops_do(&jni_dumper);
check_segment_length();
// HPROF_GC_ROOT_STICKY_CLASS
StickyClassDumper class_dumper(writer());
SystemDictionary::always_strong_oops_do(&class_dumper);
// fixes up the length of the dump record. In the case of a segmented
// heap then the HPROF_HEAP_DUMP_END record is also written.
end_of_dump();
{- -------------------------------------------
(1)
---------------------------------------- -}
// Now we clear the global variables, so that a future dumper might run.
clear_global_dumper();
clear_global_writer();
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.