欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java虛擬機(jī)啟動(dòng)過程探索

 更新時(shí)間:2022年05月27日 14:18:17   作者:Java知識(shí)圖譜  
當(dāng)我們?cè)诰帉慗ava應(yīng)用的時(shí)候,很少會(huì)注意Java程序是如何被運(yùn)行的,如何被操作系統(tǒng)管理和調(diào)度的,帶著好奇心,探索一下Java虛擬機(jī)啟動(dòng)過程

一、序言

當(dāng)我們?cè)诰帉慗ava應(yīng)用的時(shí)候,很少會(huì)注意Java程序是如何被運(yùn)行的,如何被操作系統(tǒng)管理和調(diào)度的。帶著好奇心,探索一下Java虛擬機(jī)啟動(dòng)過程。

1、素材準(zhǔn)備

Java源代碼、Java字節(jié)碼Java虛擬機(jī)、操作系統(tǒng)四個(gè)角度分解啟動(dòng)過程。

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("HelloWorld!");
    }
}

2、源代碼生成字節(jié)碼

利用Java環(huán)境提供的可執(zhí)行命令javac將源代碼編譯成字節(jié)碼文件,編譯后的字節(jié)碼文件與平臺(tái)無關(guān),可跨平臺(tái)運(yùn)行。注意區(qū)分javac命令是一個(gè)獨(dú)立的編譯應(yīng)用,源代碼編譯完成,進(jìn)程終止。java命令啟動(dòng)的虛擬機(jī)進(jìn)程的編譯過程是將字節(jié)碼指令編譯成匯編指令(二進(jìn)制指令)。

3、虛擬機(jī)解析字節(jié)碼

Java字節(jié)碼無法直接在操作系統(tǒng)上創(chuàng)建進(jìn)程,因此需要借助已經(jīng)啟動(dòng)的虛擬機(jī)進(jìn)程來解析字節(jié)碼,處理字節(jié)碼有兩種常見方式:解釋型編譯型

在命令行中每運(yùn)行java命令代表啟動(dòng)一個(gè)Java虛擬機(jī)進(jìn)程,各虛擬機(jī)相互獨(dú)立,通過命令行參數(shù)分別對(duì)虛擬機(jī)進(jìn)程進(jìn)行配置。

Java虛擬機(jī)準(zhǔn)備啟動(dòng)完畢后,便可以依次解析字節(jié)碼指令,正式運(yùn)行Java代碼部分。

4、操作系統(tǒng)管理虛擬機(jī)

操作系統(tǒng)通過進(jìn)程管理和調(diào)度Java虛擬機(jī),無法感知虛擬機(jī)間接解析Java字節(jié)碼部分。Java字節(jié)碼通過虛擬機(jī)的抽象,完成了在操作系統(tǒng)上運(yùn)行。

二、Java虛擬機(jī)

當(dāng)運(yùn)行Java應(yīng)用時(shí),需要先安裝Java環(huán)境,然而安裝的Java環(huán)境與Java應(yīng)用有什么關(guān)系,Java應(yīng)用是如何運(yùn)行起來的,下面一探究竟。

二進(jìn)制可執(zhí)行程序${JAVA_HOME}/bin/java是C++編寫經(jīng)過GCC編譯器編譯后形成的,探索Java虛擬機(jī)的運(yùn)行原理,首先需要找到相應(yīng)的源碼。

當(dāng)在安裝Java環(huán)境時(shí),會(huì)看到一個(gè)src.zip壓縮文件,解壓后里面launcher/java.c文件便是可執(zhí)行文件java命令的主要源碼。

虛擬機(jī)的啟動(dòng)入口位于launcher/java.cmain方法,整個(gè)流程分為如下幾個(gè)步驟: 配置JVM裝載環(huán)境;解析虛擬機(jī)參數(shù);設(shè)置線程棧大小;執(zhí)行Java main方法

(一)配置JVM裝載環(huán)境

從操作系統(tǒng)加載環(huán)境變量、硬件信息等運(yùn)行環(huán)境信息,為后續(xù)創(chuàng)建JVM進(jìn)程做準(zhǔn)備。

(二)命令行參數(shù)解析

裝載完JVM環(huán)境之后,需要對(duì)啟動(dòng)時(shí)命令行參數(shù)進(jìn)行解析,該過程通過ParseArguments方法實(shí)現(xiàn),并調(diào)用AddOption方法將解析完成的參數(shù)保存到JavaVMOption中。

比如常見的JavaVMOption參數(shù)在此步驟解析:

-Xms:設(shè)置堆的初始值InitialHeapSize,也是堆的最小值; 
-Xmx:設(shè)置堆的最大值MaxHeapSize;

JVM調(diào)優(yōu)各參數(shù)解析便是在此步驟完成的。

(三)執(zhí)行main方法

線程棧大小確定后,通過ContinueInNewThread方法創(chuàng)建新線程,并執(zhí)行JavaMain函數(shù),大概流程如下:

1、新建JVM實(shí)例

InitializeJVM方法調(diào)用InvocationFunctions的CreateJavaVM方法,即調(diào)用JVM.dll函數(shù)JNI_CreateJavaVM,新建一個(gè)JVM實(shí)例,該過程比較復(fù)雜。

2、加載入口類

通常在命令行中運(yùn)行如下命令即指明入口類路徑

# 直接指名入口類路徑
java HelloWorld.class
# 通過包類配置入口類路徑
java -jar HelloWorld.jar

3、查找main方法

通過GetStaticMethodID方法查找指定main方法名的靜態(tài)方法。

4、執(zhí)行main方法

通過JavaCalls::call回調(diào)執(zhí)行main方法。需要注意的是,這里執(zhí)行main方法不是Java語言的方法,是經(jīng)過虛擬機(jī)解釋(或者編譯)后,操作系統(tǒng)能夠理解的二進(jìn)制可執(zhí)行方法。

三、解析字節(jié)碼

(一)解釋字節(jié)碼

1、基于棧指令集

iconst_1    將 1 放入棧頂
iconst_1    將 1 放入棧頂
iadd        將棧頂?shù)?2 個(gè)數(shù)相加后結(jié)果放入棧頂
istore_0    將相加的結(jié)果放入局部變量表

基于棧的指令集優(yōu)點(diǎn)是虛擬機(jī)解釋器是可跨平臺(tái)移植的,換句話說不同平臺(tái)的虛擬機(jī)解釋器代碼可以復(fù)用。

2、基于寄存器指令集

mov eax,1 把 EAX 寄存器的值設(shè)為 1
add eax,1 再把這個(gè)值加 1 ,結(jié)果保存在了 EAX 寄存器

基于寄存器指令集的優(yōu)點(diǎn)是執(zhí)行速度相對(duì)于棧較快,原因是出棧入棧本身就涉及了大量的指令,而且棧是在內(nèi)存中實(shí)現(xiàn)的,更底層的匯編指令性能更高。

基于寄存器指令集的缺點(diǎn)是虛擬機(jī)解釋器是不可跨平臺(tái)移植,需要針對(duì)不同平臺(tái)的虛擬機(jī)做不同實(shí)現(xiàn)??紤]到不同平臺(tái)已經(jīng)使用不同的虛擬機(jī)程序,因此此過程多用戶透明。

虛擬機(jī)通過解釋器來翻譯字節(jié)碼文件中的指令比較順其自然,可是對(duì)于服務(wù)器端高頻執(zhí)行的程序來說,中間的翻譯過程相對(duì)耗時(shí)。解釋字節(jié)碼的方式適用于對(duì)啟動(dòng)性能要求高,并且執(zhí)行頻率較低的應(yīng)用程序。

(二)編譯字節(jié)碼

最初,JVM 中的字節(jié)碼是由解釋器( Interpreter )完成編譯的,當(dāng)虛擬機(jī)發(fā)現(xiàn)某個(gè)方法或代碼塊的運(yùn)行特別頻繁的時(shí)候,就會(huì)把這些代碼認(rèn)定為熱點(diǎn)代碼。

為了提高熱點(diǎn)代碼的執(zhí)行效率,在運(yùn)行時(shí),即時(shí)編譯器(JIT,Just In Time)會(huì)把這些代碼編譯成與本地平臺(tái)相關(guān)的機(jī)器碼,并進(jìn)行各層次的優(yōu)化,然后保存到內(nèi)存中。

在 HotSpot 虛擬機(jī)中,內(nèi)置了兩種 JIT,分別為C1 編譯器C2 編譯器,這兩個(gè)編譯器的編譯過程是不一樣的。

1、C1 編譯器

C1 編譯器是一個(gè)簡(jiǎn)單快速的編譯器,主要的關(guān)注點(diǎn)在于局部性的優(yōu)化,適用于執(zhí)行時(shí)間較短或?qū)?dòng)性能有要求的程序,也稱為Client Compiler,例如,GUI 應(yīng)用對(duì)界面啟動(dòng)速度就有一定要求。

2、C2 編譯器

C2 編譯器是為長期運(yùn)行的服務(wù)器端應(yīng)用程序做性能調(diào)優(yōu)的編譯器,適用于執(zhí)行時(shí)間較長或?qū)Ψ逯敌阅苡幸蟮某绦?,也稱為Server Compiler,例如,服務(wù)器上長期運(yùn)行的 Java 應(yīng)用對(duì)穩(wěn)定運(yùn)行就有一定的要求。

3、分層編譯

分層編譯將 JVM 的執(zhí)行狀態(tài)分為了 5 個(gè)層次:

第 0 層:程序解釋執(zhí)行,默認(rèn)開啟性能監(jiān)控功能(Profiling),如果不開啟,可觸發(fā)第二層編譯;
第 1 層:可稱為 C1 編譯,將字節(jié)碼編譯為本地代碼,進(jìn)行簡(jiǎn)單、可靠的優(yōu)化,不開啟 Profiling;
第 2 層:也稱為 C1 編譯,開啟 Profiling,僅執(zhí)行帶方法調(diào)用次數(shù)和循環(huán)回邊執(zhí)行次數(shù) profiling 的 C1 編譯;
第 3 層:也稱為 C1 編譯,執(zhí)行所有帶 Profiling 的 C1 編譯;
第 4 層:可稱為 C2 編譯,也是將字節(jié)碼編譯為本地代碼,但是會(huì)啟用一些編譯耗時(shí)較長的優(yōu)化,甚至?xí)鶕?jù)性能監(jiān)控信息進(jìn)行一些不可靠的激進(jìn)優(yōu)化。

通常情況下,C2 的執(zhí)行效率比 C1 高出30%以上。

在 Java8 中,默認(rèn)開啟分層編譯。如果只想開啟 C2,可以關(guān)閉分層編譯(-XX:-TieredCompilation),如果只想用 C1,可以在打開分層編譯的同時(shí),使用參數(shù):-XX:TieredStopAtLevel=1

通過 java -version命令行可以查看到當(dāng)前虛擬機(jī)解析字節(jié)碼的方式,mixed mode表示既有解釋模式也有即是編譯模式。

java version "1.8.0_261"
Java(TM) SE Runtime Environment (build 1.8.0_261-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)

mixed mode代表是默認(rèn)的混合編譯模式,除了這種模式外,我們還可以使用-Xint參數(shù)強(qiáng)制虛擬機(jī)運(yùn)行于只有解釋器的編譯模式下;也可以使用參數(shù)-Xcomp強(qiáng)制虛擬機(jī)運(yùn)行于只有 JIT 的編譯模式下。

僅使用解釋模式

通過命令java -Xint -version設(shè)置僅使用解釋模式,interpreted mode表示解釋模式。

java version "1.8.0_261"
Java(TM) SE Runtime Environment (build 1.8.0_261-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, interpreted mode)

僅使用編譯模式

通過命令java -Xcomp -version設(shè)置僅使用編譯模式,compiled mode表示編譯模式。在編譯模式下,程序啟動(dòng)能感覺到明顯的卡頓。

java version "1.8.0_261"
Java(TM) SE Runtime Environment (build 1.8.0_261-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, compiled mode)

四、小結(jié)

通過對(duì)Java虛擬機(jī)啟動(dòng)過程的解析,特別是即時(shí)編譯環(huán)節(jié)的理解,Java應(yīng)用運(yùn)行并不慢。當(dāng)應(yīng)用中熱點(diǎn)代碼普遍被編譯成匯編指令(二進(jìn)制可執(zhí)行命令)存放于內(nèi)存中時(shí),可近似達(dá)到C語言原生程序的運(yùn)行速度。

隨著算力與內(nèi)存成本日漸降低,通過空間復(fù)雜度置換時(shí)間復(fù)雜度的策略顯然是合理的,使用Java語言編寫需求萬千變化的應(yīng)用是第一選擇:既有跨平臺(tái)、內(nèi)存安全、框架生態(tài)豐富的優(yōu)點(diǎn),也在運(yùn)行效率方面積極改善,這種折中選擇與市場(chǎng)反饋保持一致。

到此這篇關(guān)于Java虛擬機(jī)啟動(dòng)過程解析的文章就介紹到這了,更多相關(guān)Java虛擬機(jī)啟動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論