Top


定義場所(file name)

hotspot/src/share/vm/runtime/java.cpp

説明(description)

// Note: before_exit() can be executed only once, if more than one threads
//       are trying to shutdown the VM at the same time, only one thread
//       can run before_exit() and all other threads must wait.

名前(function name)

void before_exit(JavaThread * thread) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      #define BEFORE_EXIT_NOT_RUN 0
      #define BEFORE_EXIT_RUNNING 1
      #define BEFORE_EXIT_DONE    2

  {- -------------------------------------------
  (1) before_exit() が実行されるのは 1回だけにしたいので, 
      _before_exit_status という関数内 static 変数を使って排他を行う.

      _before_exit_status を BEFORE_EXIT_NOT_RUN から 
      BEFORE_EXIT_RUNNING に書き換えたスレッドだけが実際の処理を行う.
      (ここにたどり着いたその他のスレッドは 
      _before_exit_status が BEFORE_EXIT_DONE に変わるまで待ってからリターンするだけ)

      (なおコメントによると, before_exit() 全体を Mutex で保護するのはダメ, )
      ---------------------------------------- -}

      static jint volatile _before_exit_status = BEFORE_EXIT_NOT_RUN;

      // Note: don't use a Mutex to guard the entire before_exit(), as
      // JVMTI post_thread_end_event and post_vm_death_event will run native code.
      // A CAS or OSMutex would work just fine but then we need to manipulate
      // thread state for Safepoint. Here we use Monitor wait() and notify_all()
      // for synchronization.
      { MutexLocker ml(BeforeExit_lock);
        switch (_before_exit_status) {
        case BEFORE_EXIT_NOT_RUN:
          _before_exit_status = BEFORE_EXIT_RUNNING;
          break;
        case BEFORE_EXIT_RUNNING:
          while (_before_exit_status == BEFORE_EXIT_RUNNING) {
            BeforeExit_lock->wait();
          }
          assert(_before_exit_status == BEFORE_EXIT_DONE, "invalid state");
          return;
        case BEFORE_EXIT_DONE:
          return;
        }
      }

  {- -------------------------------------------
  (1) exit_procs 大域変数に登録されている ExitProc の内容を全て実行する.

      (<= とはいえ ExitProc は使用されていないので, 実際には何も実行されないが...)
      (See: ExitProc)
      ---------------------------------------- -}

      // The only difference between this and Win32's _onexit procs is that
      // this version is invoked before any threads get killed.
      ExitProc* current = exit_procs;
      while (current != NULL) {
        ExitProc* next = current->next();
        current->evaluate();
        delete current;
        current = next;
      }

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      // Hang forever on exit if we're reporting an error.
      if (ShowMessageBoxOnError && is_error_reported()) {
        os::infinite_sleep();
      }

  {- -------------------------------------------
  (1) もし PeriodicTask を使用していた場合は, 
      WatcherThread::stop() で WatcherThread を終了させる (See: WatcherThread).
      ---------------------------------------- -}

      // Terminate watcher thread - must before disenrolling any periodic task
      if (PeriodicTask::num_tasks() > 0)
        WatcherThread::stop();

  {- -------------------------------------------
  (1) FlatProfiler を使用していた場合は, プロファイル情報を出力する.
      (See: FlatProfiler)
      ---------------------------------------- -}

      // Print statistics gathered (profiling ...)
      if (Arguments::has_profile()) {
        FlatProfiler::disengage();
        FlatProfiler::print(10);
      }

  {- -------------------------------------------
  (1) StatSampler を停止させる (See: StatSampler).
      ---------------------------------------- -}

      // shut down the StatSampler task
      StatSampler::disengage();
      StatSampler::destroy();

  {- -------------------------------------------
  (1) GC アルゴリズムが CMS だった場合は ConcurrentMarkSweepThread を停止させる.
      ---------------------------------------- -}

    #ifndef SERIALGC
      // stop CMS threads
      if (UseConcMarkSweepGC) {
        ConcurrentMarkSweepThread::stop();
      }
    #endif // SERIALGC

  {- -------------------------------------------
  (1) (トレース出力)
      ---------------------------------------- -}

      // Print GC/heap related information.
      if (PrintGCDetails) {
        Universe::print();
        AdaptiveSizePolicyOutput(0);
      }


  {- -------------------------------------------
  (1) AllocationProfiler を使用していた場合は, プロファイル情報を出力する.
      (See: AllocationProfiler)
      ---------------------------------------- -}

      if (Arguments::has_alloc_profile()) {
        HandleMark hm;
        // Do one last collection to enumerate all the objects
        // allocated since the last one.
        Universe::heap()->collect(GCCause::_allocation_profiler);
        AllocationProfiler::disengage();
        AllocationProfiler::print(0);
      }

  {- -------------------------------------------
  (1) BytecodeHistogram を使用していた場合は, プロファイル情報を出力する.
      (See: BytecodeHistogram)
      ---------------------------------------- -}

      if (PrintBytecodeHistogram) {
        BytecodeHistogram::print();
      }

  {- -------------------------------------------
  (1) (JVMTI のフック点)
      ---------------------------------------- -}

      if (JvmtiExport::should_post_thread_life()) {
        JvmtiExport::post_thread_end(thread);
      }

  {- -------------------------------------------
  (1) (JVMTI のフック点)
      ---------------------------------------- -}

      // Always call even when there are not JVMTI environments yet, since environments
      // may be attached late and JVMTI must track phases of VM execution
      JvmtiExport::post_vm_death();

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      Threads::shutdown_vm_agents();

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      // Terminate the signal thread
      // Note: we don't wait until it actually dies.
      os::terminate_signal_thread();

  {- -------------------------------------------
  (1) (トレース出力)
      ---------------------------------------- -}

      print_statistics();
      Universe::heap()->print_tracing_info();

  {- -------------------------------------------
  (1) 全ての処理が終わったので, _before_exit_status を BEFORE_EXIT_DONE に変更する.
      また, 終了を待っているスレッドがいるかもしれないので notify_all() も呼んでおく.
      ---------------------------------------- -}

      { MutexLocker ml(BeforeExit_lock);
        _before_exit_status = BEFORE_EXIT_DONE;
        BeforeExit_lock->notify_all();
      }

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      #undef BEFORE_EXIT_NOT_RUN
      #undef BEFORE_EXIT_RUNNING
      #undef BEFORE_EXIT_DONE
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.