Top


定義場所(file name)

hotspot/src/share/vm/services/heapDumper.cpp

説明(description)

// 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.

名前(function name)

void VM_HeapDumper::doit() {

本体部(body)

  {- -------------------------------------------
  (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.