JVMソース分析のJVM起動プロセス
4462 ワード
前言
Javaクラスのmainメソッドを実行すると、プログラムが実行されます.mainメソッドの背後には、仮想マシンに何が起こっているのでしょうか.もしあなたがこれに興味があるならば、本文はあなたに1つの答えをあげると信じて、本文の分析するopenjdkバージョンはopenjdk-7-fcs-src-b 147-27です
仮想マシンの起動ポートが
1.JVMマウント環境の構成
Javaコードの実行には、JVM環境が必要です.JVM環境の作成には、JVM.dllファイルの検索とマウントの2つのセクションがあります.
JVM.dllファイルの検索
大まかな実装ロジック:1、
JVM.dllファイルのマウント
仮想マシンの関数呼び出しを初期化します.つまり、JVMのメソッドでJVM.dllファイルで定義されている関数を呼び出します.
1、
2、仮想マシンパラメータ解析
JVM環境をマウントした後、起動パラメータを解析する必要があるが、実際にはJVM環境をマウントする過程ですでに一部のパラメータが解析されており、この過程は
AddOptionメソッドは次のように実装されます.
ここでは
パラメータ処理
ここには、1、-Xmn:新世代のサイズNewSizeとMaxNewSizeを設定する3つの一般的なパラメータのみがリストされます.2、-Xms:スタックの初期値InitialHeapSizeを設定し、スタックの最小値でもあります.3、-Xmx:ヒープの最大値MaxHeapSizeを設定する.
パラメータ検証
1、パラメータが
3、スレッドスタックサイズの設定
起動パラメータが
4、Java mainメソッドの実行
スレッドスタックのサイズが決定された後、
1、新規JVMインスタンス
2、主クラスのclassをロードする
Javaの実行方式にはjar方式とclass方式の2種類があります.
JAr方式
1.
class方式
1.
3、mainメソッドの検索
最終呼び出し
ここで、
4、mainメソッドの実行
1、パラメータ配列を再作成する;2.mainIDはmainメソッドのエントリアドレスであり、
jni_invoke_staticは次のように実現されます.
最終的には、
作者:占小狼リンク:https://www.jianshu.com/p/b91258bc08ac 出典:簡書
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_CreateJavaVM
とJNI_GetDefaultJavaVMInitArgs
をInvocationFunctions変数のCreateJavaVM
とGetDefaultJavaVMInitArgs
の関数ポインタ変数にバインドする.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
に定義され、以下のように実現される.ThreadStackSize
はglobals.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.dll
のjni_CallStaticVoidMethodV
関数を呼び出し、以下のように実現する.jni_invoke_staticは次のように実現されます.
最終的には、
JavaCalls::call
によってmainメソッドが実行される.作者:占小狼リンク:https://www.jianshu.com/p/b91258bc08ac 出典:簡書