JVM底層原理解析
本文轉(zhuǎn)載自微信公眾號(hào)「極客重生」,作者極客重生。轉(zhuǎn)載本文請(qǐng)聯(lián)系極客重生公眾號(hào)。
hi ,大家好,我是極客重生的Alex,今天分享一篇JVM底層原理的文章,希望可以幫助大家了解一下語(yǔ)言虛擬機(jī)一些設(shè)計(jì)原理,不管你當(dāng)前使用語(yǔ)言是C,C++,Golang,Python等,很多思想和原理是相通的,可以借鑒。
比如之前分析內(nèi)核虛擬機(jī)eBPF架構(gòu):
詳細(xì)請(qǐng)看:Linux網(wǎng)絡(luò)新技術(shù)基石 |eBPF and XDP
在本文中,您將學(xué)習(xí)
- JVM架構(gòu)
- 軟件代碼編譯執(zhí)行流程
- C代碼編譯執(zhí)行過(guò)程
- Java代碼編譯執(zhí)行過(guò)程
- 為什么Java既是解釋型語(yǔ)言又是編譯型語(yǔ)言?
- 為什么 Java 很慢?
什么是JVM?
Java 虛擬機(jī) (JVM)是提供運(yùn)行時(shí)環(huán)境來(lái)驅(qū)動(dòng) Java 代碼或應(yīng)用程序的引擎。它將 Java 字節(jié)碼轉(zhuǎn)換為機(jī)器語(yǔ)言。JVM 是 Java 運(yùn)行環(huán)境 (JRE) 的一部分。在其他編程語(yǔ)言中,編譯器為特定系統(tǒng)生成機(jī)器代碼。但是,Java編譯器為稱(chēng)為Java 虛擬機(jī)的虛擬機(jī)生成代碼。
JVM的工作原理
首先,Java 代碼被編譯成字節(jié)碼,這個(gè)字節(jié)碼在不同的機(jī)器上被解釋?zhuān)谥鳈C(jī)系統(tǒng)和 Java 源代碼之間,字節(jié)碼是一種中介語(yǔ)言,Java 中的 JVM 負(fù)責(zé)分配內(nèi)存空間。
Java 虛擬機(jī) (JVM) 的工作
JVM架構(gòu)
讓我們了解 JVM 的架構(gòu)。Java 中的 JVM 架構(gòu)包含類(lèi)加載器、內(nèi)存區(qū)、執(zhí)行引擎等。
Java 虛擬機(jī)架構(gòu)
1) 類(lèi)加載器
類(lèi)加載器是用于加載類(lèi)文件的子系統(tǒng)。它執(zhí)行三個(gè)主要功能,即。加載、鏈接和初始化。
2) 方法區(qū)
JVM 方法區(qū)存儲(chǔ)類(lèi)結(jié)構(gòu),如元數(shù)據(jù)、常量運(yùn)行時(shí)池和方法代碼。
3) 堆
所有的Objects及其相關(guān)的實(shí)例變量和數(shù)組都存儲(chǔ)在堆中。此內(nèi)存是通用的,并在多個(gè)線程之間共享。
4) JVM 語(yǔ)言棧
Java 語(yǔ)言堆棧存儲(chǔ)局部變量,和部分結(jié)果,每個(gè)線程都有自己的 JVM 堆棧,在創(chuàng)建線程時(shí)同時(shí)創(chuàng)建。每當(dāng)調(diào)用方法時(shí)都會(huì)創(chuàng)建一個(gè)新的,并在方法調(diào)用過(guò)程完成時(shí)將其刪除。
5) PC 寄存器
PC 寄存器存儲(chǔ)當(dāng)前正在執(zhí)行的 Java 虛擬機(jī)指令的地址。在 Java 中,每個(gè)線程都有其獨(dú)立的 PC 寄存器。
6) 本地方法棧
本機(jī)方法棧持有本機(jī)代碼的指令取決于本機(jī)庫(kù)。它是用另一種語(yǔ)言而不是 Java 編寫(xiě)的。
7) 執(zhí)行引擎
它是一種用于測(cè)試硬件、軟件或完整系統(tǒng)的軟件。測(cè)試執(zhí)行引擎從不攜帶有關(guān)被測(cè)產(chǎn)品的任何信息。
8) 本地方法接口
本機(jī)方法接口是一個(gè)編程框架。它允許在 JVM 中運(yùn)行的 Java 代碼由庫(kù)和本機(jī)應(yīng)用程序調(diào)用。
9) 本地方法庫(kù)
本機(jī)庫(kù)是執(zhí)行引擎所需的本機(jī)庫(kù)(C、C++)的集合。
軟件代碼編譯執(zhí)行流程
為了編寫(xiě)和執(zhí)行軟件程序,您需要以下內(nèi)容
1) 編輯器 – 要輸入您的程序,可以使用記事本。
2) 編譯器 ——將您的高級(jí)語(yǔ)言程序轉(zhuǎn)換為本地機(jī)器代碼。
3) 鏈接器 ——將主程序中的不同程序文件引用組合在一起。
4) Loader – 將您的輔助存儲(chǔ)設(shè)備(如硬盤(pán)、閃存驅(qū)動(dòng)器、CD )中的文件加載到 RAM 中以供執(zhí)行。執(zhí)行代碼時(shí)會(huì)自動(dòng)完成加載。
5) 執(zhí)行– 由您的操作系統(tǒng)和處理器處理的代碼的實(shí)際執(zhí)行。
C代碼編譯執(zhí)行過(guò)程
了解Java中的Java編譯過(guò)程。首先讓我們快速了解一下 C 中的編譯和鏈接過(guò)程。
假設(shè)在 main 中,您調(diào)用了兩個(gè)函數(shù) f1 和 f2。main 函數(shù)存儲(chǔ)在文件 a1.c 中。
函數(shù) f1 存儲(chǔ)在文件 a2.c 中
函數(shù) f2 存儲(chǔ)在文件 a3.c 中
所有這些文件,即 a1.c、a2.c 和 a3.c,都被提供給編譯器。其輸出是相應(yīng)的目標(biāo)文件,即機(jī)器代碼。
下一步是在鏈接器的幫助下將所有這些目標(biāo)文件集成到一個(gè) .exe 文件中。鏈接器會(huì)將所有這些文件組合在一起并生成 .exe 文件。
在程序運(yùn)行過(guò)程中,加載程序會(huì)將 a.exe 加載到 RAM 中執(zhí)行。
Java VM 中的 Java 代碼編譯和執(zhí)行
讓我們看看 JAVA 的編譯執(zhí)行過(guò)程。在您的主文件中,您有兩個(gè)方法 f1 和 f2。
- main方法存放在文件a1.java中
- f1 作為 a2.java 存儲(chǔ)在文件中
- f2 作為 a3.java 存儲(chǔ)在文件中
編譯器將編譯這三個(gè)文件,并生成 3 個(gè)對(duì)應(yīng)的 .class 文件,其中包含字節(jié)碼。與 C 不同,沒(méi)有進(jìn)行鏈接。Java VM 或 Java 虛擬機(jī)駐留在 RAM 上。在執(zhí)行期間,使用類(lèi)加載器將類(lèi)文件帶到 RAM 中。字節(jié)碼已驗(yàn)證是否存在任何安全漏洞。
接下來(lái),執(zhí)行引擎會(huì)將字節(jié)碼轉(zhuǎn)換為本地機(jī)器碼。這只是及時(shí)編譯,這是Java相對(duì)較慢的主要原因之一。
注意:JIT或即時(shí)編譯器是 Java 虛擬機(jī) (JVM) 的一部分。它同時(shí)轉(zhuǎn)化具有相似功能的部分字節(jié)碼。
為什么Java既是解釋型語(yǔ)言又是編譯型語(yǔ)言?
編程語(yǔ)言被分類(lèi)為
- 高級(jí)語(yǔ)言,例如C++、Java
- 中級(jí)語(yǔ)言,例如C
- 低級(jí)語(yǔ)言,例如匯編
- 最后是最低級(jí)別的機(jī)器語(yǔ)言。
編譯器是一個(gè)程序,它把程序從一個(gè)級(jí)別轉(zhuǎn)化到另外一個(gè)級(jí)別(一般是從高到低),比如把C++ 程序轉(zhuǎn)化到機(jī)器碼。
java編譯器將高級(jí)java代碼轉(zhuǎn)換成字節(jié)碼(也是一種機(jī)器碼)。
解釋器是一個(gè)程序,它把程序轉(zhuǎn)化為相同等級(jí)的其他語(yǔ)言,比如把Java程序轉(zhuǎn)換成C++。
在 Java 中,Jit生成器將字節(jié)碼轉(zhuǎn)換為處于相同級(jí)別的本機(jī)機(jī)器代碼,因此,Java 既是編譯型語(yǔ)言,又是解釋型語(yǔ)言。
為什么 Java 很慢?
Java 運(yùn)行緩慢的兩個(gè)主要原因是
動(dòng)態(tài)鏈接:與 C 不同,鏈接是在運(yùn)行時(shí)完成的,每次程序在 Java 中運(yùn)行時(shí)。
運(yùn)行時(shí)解釋器:字節(jié)碼到本地機(jī)器碼的轉(zhuǎn)換是在 Java 運(yùn)行時(shí)完成的,這進(jìn)一步減慢了速度。
但是,最新版本的 Java 在很大程度上解決了性能瓶頸。
總結(jié):
- JVM 的完整形式是Java Virtual Machine.(Java虛擬機(jī)),Java 中的 JVM 是驅(qū)動(dòng) Java 代碼的引擎,它將 Java 字節(jié)碼轉(zhuǎn)換為機(jī)器語(yǔ)言。
- Java 中的 JVM 架構(gòu)包含類(lèi)加載器、內(nèi)存區(qū)、執(zhí)行引擎等。
- 在 JVM 中,Java 代碼被編譯為字節(jié)碼。這個(gè)字節(jié)碼在不同的機(jī)器上被解釋成不同的機(jī)器碼。
- JIT 代表即時(shí)編譯器。JIT 是 Java 虛擬機(jī) (JVM) 的一部分。它用于加快執(zhí)行時(shí)間。
- 與其他編譯器機(jī)器相比,Java 中的 JVM 執(zhí)行速度可能較慢。