JVMソース分析のJVM起動プロセス

4462 ワード

前言
Javaクラスのmainメソッドを実行すると、プログラムが実行されます.mainメソッドの背後には、仮想マシンに何が起こっているのでしょうか.もしあなたがこれに興味があるならば、本文はあなたに1つの答えをあげると信じて、本文の分析するopenjdkバージョンはopenjdk-7-fcs-src-b 147-27です
class BootStrap {
    public static void main(String[] args) {
        for (String str : args) {
            System.out.println(str);
        }
    }
}

java BootStrap -Xms6G -Xmx8G -Xmn3G -Xss512k 
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC

仮想マシンの起動ポートがshare/tools/launcher/java.cにあるmainメソッドは、1、JVMマウント環境の構成2、仮想マシンパラメータの解析3、スレッドスタックサイズの設定4、Java mainメソッドの実行のいくつかのステップに分かれています.
1.JVMマウント環境の構成
Javaコードの実行には、JVM環境が必要です.JVM環境の作成には、JVM.dllファイルの検索とマウントの2つのセクションがあります.
JVM.dllファイルの検索CreateExecutionEnvironment方法で実現し、現在のJRE環境の経路とシステムバージョンに基づいてjvm.cfgファイルを探し、windowsは以下のように実現する.
大まかな実装ロジック:1、GetJREPath現在のJRE環境の所在経路を検索する;2、ReadKnownVms JRE \lib\ARCH(CPU )\JVM.cfgファイルを読み取り、そのうちARCH(CPU )GetArch方法で取得され、windowではamd 64、ia 64、i 386の3つのケースがある.3、CheckJvmTypeは現在のJVMタイプを決定し、まず-J-XXaltjvm=または-J-XXaltjvm=のパラメータによって指定されたかどうかを判断し、もしそうでなければ、JVM.cfgファイルで構成された最初のタイプを読み取る.4、GetJVMPath前のステップで決定したJVMタイプに基づいて、対応するJVM.dllファイルを見つける.
JVM.dllファイルのマウント
仮想マシンの関数呼び出しを初期化します.つまり、JVMのメソッドでJVM.dllファイルで定義されている関数を呼び出します.
1、LoadLibrary方法JVM.dll動的接続ライブラリをマウントする;2.JVM.dllファイルで定義された関数JNI_CreateJavaVMJNI_GetDefaultJavaVMInitArgsをInvocationFunctions変数のCreateJavaVMGetDefaultJavaVMInitArgsの関数ポインタ変数にバインドする.
2、仮想マシンパラメータ解析
JVM環境をマウントした後、起動パラメータを解析する必要があるが、実際にはJVM環境をマウントする過程ですでに一部のパラメータが解析されており、この過程はParseArgumentsの方法で実現され、AddOptionの方法を呼び出して解析完了したパラメータをJavaVMOptionに保存し、JavaVMOptionの構造は以下のように実現されている.
AddOptionメソッドは次のように実装されます.
ここでは-Xssパラメータに対して特殊な処理を行い、threadStackSizeを設定する.パラメータフォーマットは比較的特殊であるため、他はkey/valueキー値ペアであり、-Xss512のフォーマットである.後続のArgumentsクラスはJavaVMOptionデータを再処理し、パラメータの妥当性を検証する.
パラメータ処理Arguments::parse_each_vm_init_argメソッドは解析されたJavaVMOptionデータの処理を担当し、一部は以下のように実現される.
ここには、1、-Xmn:新世代のサイズNewSizeとMaxNewSizeを設定する3つの一般的なパラメータのみがリストされます.2、-Xms:スタックの初期値InitialHeapSizeを設定し、スタックの最小値でもあります.3、-Xmx:ヒープの最大値MaxHeapSizeを設定する.
パラメータ検証Arguments::check_gc_consistencyメソッドは、仮想マシン起動パラメータにおけるGCの構成の妥当性を検証し、以下のように実現する.
1、パラメータが-XX:+UseSerialGC -XX:+UseParallelGCの場合、UseSerialGCとUseParallelGCは互換性がないため、JVM起動時にエラーメッセージが投げ出される.2、パラメータが-XX:+UseConcMarkSweepGC -XX:+UseParNewGCの場合、UseConcMarkSweepGCとUseParNewGCは互換性があり、JVMは正常に起動できる.
3、スレッドスタックサイズの設定
起動パラメータが-Xss、すなわちthreadStackSizeが0に設定されていない場合、InvocationFunctionsを呼び出すGetDefaultJavaVMInitArgsメソッドは、JavaVMの初期化パラメータ、すなわちJVM.dll関数JNI_GetDefaultJavaVMInitArgsを呼び出し、share\vm\prims\jni.cppに定義され、以下のように実現される.ThreadStackSizeglobals.hppに定義され、現在のシステムタイプに応じて対応するプロファイルがロードされるため、異なるシステムではThreadStackSizeのデフォルト値も異なる.
4、Java mainメソッドの実行
スレッドスタックのサイズが決定された後、ContinueInNewThreadの方法で新しいスレッドが作成され、JavaMain関数が実行されます.JavaMain関数の概要は次のとおりです.
1、新規JVMインスタンスInitializeJVMメソッドInvocationFunctionsを呼び出すCreateJavaVMメソッド、すなわちJVM.dll関数JNI_CreateJavaVMを呼び出し、JVMインスタンスを新規作成します.このプロセスは複雑で、後続の文章で分析されます.
2、主クラスのclassをロードする
Javaの実行方式にはjar方式とclass方式の2種類があります.
JAr方式
1.GetMainClassNameメソッドを呼び出して、META-INF/MANIFEST.MFファイルに指定されたMain-Classの主なクラス名を見つける.2、LoadClassメソッドを呼び出してメインクラスのclassファイルをロードする.
class方式
1.NewPlatformStringメソッドを呼び出してクラス名のStringオブジェクトを作成する.2、LoadClassメソッドを呼び出してメインクラスのclassファイルをロードする.
3、mainメソッドの検索GetStaticMethodIDメソッドによって指定されたメソッド名の静的メソッドが検索され、以下のように実現される.
最終呼び出しJVM.dll関数jni_GetStaticMethodID実装
ここで、get_method_idメソッドは、クラスファイルに対応するinstanceKlassオブジェクトに基づいて指定メソッドを検索します.
4、mainメソッドの実行
1、パラメータ配列を再作成する;2.mainIDはmainメソッドのエントリアドレスであり、CallStaticVoidMethodメソッドは最終的にJVM.dlljni_CallStaticVoidMethodV関数を呼び出し、以下のように実現する.
jni_invoke_staticは次のように実現されます.
 
最終的には、JavaCalls::callによってmainメソッドが実行される.
作者:占小狼リンク:https://www.jianshu.com/p/b91258bc08ac 出典:簡書