Up Top

HotSpot の起動/終了処理 : HotSpot の起動処理の流れ (JNI_CreateJavaVM() の処理の流れ)


概要(Summary)

(以下の内容はほとんど HotSpot Runtime Overview の受け売り. こちらも参照のこと)

JNI_CreateJavaVM() による HotSpot の起動処理は以下のようになる.

  1. 複数のスレッドが同時に JNI_CreateJavaVM() を呼び出していないか検査する.

(現状の実装では, 1プロセス内に最大1つしか HotSpot は生成させない)

(ちなみに, 初期化プロセスが "point of no return" という点まで到達すると, 再初期化不可能な static なデータ構造を生成し終わるため, もう HotSpot は作れなくなる. この検査は, そこに到達する前に別のスレッドが JNI_CreateJavaVM() を呼んだ場合用のチェック)

  1. Threads::create_vm() を呼び出す. この中で初期化処理の大半が行われる.

    1. JNI のバージョンがサポート範囲かどうか確認.
    2. ostream_init() により, ostream を gc log のために初期化する.
    3. os::init() により, OS モジュール (乱数生成機, 現在のPID, 高精度タイマー, etc) を初期化する.
    4. Arguments::parse() により, コマンドライン引数などを処理する.
    5. os::init_2() により, コマンドライン引数に基づいて OS モジュールをさらに生成&初期化する.

    (e.g. synchronization, stack, memory, safepoint pages, etc).

    (また, その他のライブラリ(libzip, libjava, etc) をロードしたり, シグナルハンドラを初期化したりもする) 1. ostream_init_log() で, output stream logger を初期化する.

    (必要な agent libraries (hprof, jdi) も初期化してスタートさせる) 1. ThreadLocalStorage::init() 等で, スレッドの状態や TLS などを初期化する. 1. vm_init_globals() で, 大域データを初期化する.

    (e.g. event log, OS synchronization primitives, perfMemory (performance memory), chunkPool (memory allocator), etc) 1. この段階でスレッドが作れるようになる.

    Java の main スレッドが作られ, 現在実行中のネイティブスレッドに対応付けられる (ただし, このスレッドは the known list of the Threads には追加されない ??)

    ちなみに, ここが "point of no return" (set_as_starting_thread() の途中で失敗したらやり直せない) 1. ObjectMonitor::Initialize() で, Java レベルの同期排他機構の初期化を行う. 1. init_globals() で, 残りの大域モジュールを初期化する.

    (e.g. BootClassLoader, CodeCache, Interpreter, Compiler, JNI, SystemDictionary, Universe, etc)

    ちなみに, ここも "point of no return" (init_globals() の途中で失敗したらやり直せない) 1. main スレッドが list (the known list of the Threads??) に追加される.

    (<= なお Thread_Lock(??) を最初にロックするはこの時らしい) 1. Universe::verify() で, Universe のチェックを行う. 1. VMThread::create() で, VMThread を生成する. 1. 現在の状態を知らせるための適切な JVMTI イベントが発行される. 1. initialize_class() を用いて, 種々の Java クラスがロードされ初期化される.

    (e.g. java.lang.String, java.lang.System, java.lang.ThreadGroup, java.lang.Thread, java.lang.reflect.Method, java.lang.ref.Finalizer, java.lang.Class, and the rest of the System)

備考(Notes)

なお HotSpot 内では, C++ の global initializer 等は使用していない.

代わりに, 明示的に初期化用関数を用意し, vm_init_globals() や init_globals() から呼び出すという構成にしている.

コメントによると, 「この方がリンク時間が少なくとも2倍は速くなるし, 初期化の順番もコントロールできるため」とのこと.

このため新しくモジュールを追加する場合にも, 「グローバルにオブジェクトを確保するのではなく, ポインタを入れる場所だけ確保しておいて, 明示的に初期化用関数を init.cpp 内で呼び出すように」, とのこと.

    ((cite: hotspot/src/share/vm/runtime/init.hpp))
    // init_globals replaces C++ global objects so we can use the standard linker
    // to link Delta (which is at least twice as fast as using the GNU C++ linker).
    // Also, init.c gives explicit control over the sequence of initialization.

    // Programming convention: instead of using a global object (e,g, "Foo foo;"),
    // use "Foo* foo;", create a function init_foo() in foo.c, and add a call
    // to init_foo in init.cpp.

    jint init_globals();     // call constructors at startup (main Java thread)
    void vm_init_globals();  // call constructors at startup (VM thread)
    void exit_globals();     // call destructors before exit

処理の流れ (概要)(Execution Flows : Summary)

JNI_CreateJavaVM()
-> Threads::create_vm()    (← この中で実際の初期化処理の大半が行われる)
   ->
   -> ostream_init()
   ->
   -> os::init()
   ->
   -> Arguments::parse()
   ->
   -> os::init_2()
   ->
   -> ostream_init_log()
   ->
   -> ThreadLocalStorage::init()
   ->
   -> vm_init_globals()
      -> check_ThreadShadow()
      -> basic_types_init()
      -> eventlog_init()
      -> mutex_init()
      -> chunkpool_init()
      -> perfMemory_init()
   ->
   -> ObjectMonitor::Initialize()
   ->
   -> init_globals()
      -> management_init()
      -> bytecodes_init()                (See: here for details)
      -> classLoader_init()              (See: here for details)
      -> codeCache_init()                 
      -> VM_Version_init()                
      -> stubRoutines_init1()             
      -> universe_init()                 (See: here for details)
      -> interpreter_init()              (See: here for details)
      -> invocationCounter_init()         
      -> marksweep_init()                 
      -> accessFlags_init()               
      -> templateTable_init()            (See: here for details)
      -> InterfaceSupport_init()
      -> SharedRuntime::generate_stubs()
      -> universe2_init()
         -> Universe::genesis()
      -> referenceProcessor_init()       (See: here for details)
      -> jni_handles_init()
      -> vmStructs_init()
      -> vtableStubs_init()
      -> InlineCacheBuffer_init()
      -> compilerOracle_init()
      -> compilationPolicy_init()        (See: here for details)
      -> VMRegImpl::set_regName()
      -> universe_post_init()
      -> javaClasses_init()
      -> stubRoutines_init2()
   ->
   -> Universe::verify()
   ->
   -> VMThread::create()                 (See: here for details)
   ->
   -> initialize_class()                 (See: here for details)
   -> 
   -> quicken_jni_functions()            (See: here for details)
   -> ... #TODO
   -> 
   -> CompileBroker::compilation_init()  (See: here for details)
   -> Management::initialize()           (See: here for details)
   -> FlatProfiler::engage()
   -> AllocationProfiler::engage()
   -> MemProfiler::engage()
   -> StatSampler::engage()
   -> JniPeriodicChecker::engage()
   -> BiasedLocking::init()              (See: here for details)
   -> WatcherThread::start()
   -> os::init_3()

処理の流れ (詳細)(Execution Flows : Details)

JNI_CreateJavaVM()

See: here for details

Threads::create_vm()

See: here for details

...#TODO

Arguments::parse()

(#Under Construction)

...#TODO

vm_init_globals()

See: here for details

init_globals()

See: here for details

...#TODO

universe2_init()

See: here for details

Universe::genesis()

See: here for details

...#TODO

universe_post_init()

See: here for details

...#TODO


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