柚子快報(bào)邀請碼778899分享:JVM的工作流程
柚子快報(bào)邀請碼778899分享:JVM的工作流程
目錄
1.JVM 簡介?
2.JVM 執(zhí)行流程?
3. JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)
? ?3.1 堆(線程共享)
3.3 本地方法棧(線程私有)
3.4 程序計(jì)數(shù)器(線程私有)
3.5 方法區(qū)(線程共享)?
4.JVM 類加載
① 類加載過程
1) 加載
2) 驗(yàn)證
3) 準(zhǔn)備
4) 解析
5) 初始化
② 雙親委派模型
雙親委派模型的優(yōu)點(diǎn)
1.JVM 簡介?
? ? ? ?
JVM
是
Java Virtual Machine
的簡稱,意為
Java
虛擬機(jī)。
虛擬機(jī)是指通過軟件模擬的具有完整硬件功能的、運(yùn)行在一個(gè)完全隔離的環(huán)境中的完整計(jì)算機(jī)系統(tǒng)。
? ? ? ?常見的虛擬機(jī):
JVM
、
VMwave
、
Virtual Box
2.JVM 執(zhí)行流程?
? ? ?程序在執(zhí)行之前先要把java代碼轉(zhuǎn)換成字節(jié)碼(class文件),JVM 首先需要把字節(jié)碼通過一定的方式 類加載器(ClassLoader) 把文件加載到內(nèi)存中 運(yùn)行時(shí)數(shù)據(jù)區(qū)(Runtime Data Area) ,而字節(jié)碼文件是 JVM 的一套指令集規(guī)范,并不能直接交個(gè)底層操作系統(tǒng)去執(zhí)行,因此需要特定的命令解析器 執(zhí)行引擎(Execution Engine)將字節(jié)碼翻譯成底層系統(tǒng)指令再交由CPU去執(zhí)行,而這個(gè)過程中需要調(diào)用其他語言的接口 本地庫接口(Native Interface) 來實(shí)現(xiàn)整個(gè)程序的功能,這就是這4個(gè)主要組成部 分的職責(zé)與功能。
?????????????????????????????????
3. JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)
? ?????????JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)域也叫內(nèi)存布局,但需要注意的是它和
Java
內(nèi)存模型(
(Java Memory Model
,簡稱 JMM)完全不同,屬于完全不同的兩個(gè)概念,它由以下
5
大部分組成:
? ??
? ?3.1 堆(線程共享)
? ? 堆的作用:程序中創(chuàng)建的所有對象(new)都在保存在堆中
? ? ?堆里面分為兩個(gè)區(qū)域:新生代和老生代,新生代放新建的對象,當(dāng)經(jīng)過一定
GC
次數(shù)之后還存活的對象會放入老生代。新生代還有 3
個(gè)區(qū)域:一個(gè)
Endn +
兩個(gè)
Survivor
(
S0/S1
)。
?3.2 Java虛擬機(jī)棧(線程私有)
????????Java 虛擬機(jī)棧的作用:
Java
虛擬機(jī)棧的生命周期和線程相同,
Java
虛擬機(jī)棧描述的是
Java
方法執(zhí)行的內(nèi)存模型:每個(gè)方法在執(zhí)行的同時(shí)都會創(chuàng)建一個(gè)
棧幀
(Stack Frame
)用于
存儲局部變表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息
。咱們常說的堆內(nèi)存、棧內(nèi)存中,棧內(nèi)存指的就是虛擬棧。
?Java 虛擬機(jī)棧中包含了以下 4 部分:
3.3 本地方法棧(線程私有)
? ? 本地方法棧和虛擬機(jī)棧類似,只不過
Java
虛擬機(jī)棧是給
JVM
使用的,而本地方法棧是給本地方法使用 的。
3.4 程序計(jì)數(shù)器(線程私有)
????????程序計(jì)數(shù)器的作用:用來記錄當(dāng)前線程執(zhí)行的行號的。
????????程序計(jì)數(shù)器是一塊比較小的內(nèi)存空間,可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。
????????如果當(dāng)前線程正在執(zhí)行的是一個(gè)Java
方法,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址; 如果正在執(zhí)行的是一個(gè)Native
方法,這個(gè)計(jì)數(shù)器值為空。
什么是線程私有?
? ????????
由于JVM的多線程是通過線程輪流切換并分配處理器執(zhí)行時(shí)間的方式來實(shí)現(xiàn),因此在任何一個(gè)確定的時(shí) 刻,一個(gè)處理器(多核處理器則指的是一個(gè)內(nèi)核)都只會執(zhí)行一條線程中的指令。因此為了切換線程后能 恢復(fù)到正確的執(zhí)行位置,每條線程都需要獨(dú)立的程序計(jì)數(shù)器,各條線程之間計(jì)數(shù)器互不影響,獨(dú)立存 儲。我們就把類似這類區(qū)域稱之為"線程私有"的內(nèi)存。
3.5 方法區(qū)(線程共享)?
????????方法區(qū)的作用:用來存儲被虛擬機(jī)加載的類信息、常量、靜態(tài)變量(static)、即時(shí)編譯器編譯后的代碼等數(shù)據(jù) 的。
? ???????在 HotSpot 虛擬機(jī)的實(shí)現(xiàn)中,在 JDK 7 時(shí)此區(qū)域 叫做永久代(PermGen),JDK 8 中叫做元空間(Metaspace)。
? ? ? 運(yùn)行時(shí)常量池
運(yùn)行時(shí)常量池是方法區(qū)的一部分,存放字面量與符號引用。
字面量
:
字符串
(JDK 8
移動到堆中
)
、
final
常量、基本數(shù)據(jù)類型的值。
符號引用
:
類和結(jié)構(gòu)的完全限定名、字段的名稱和描述符、方法的名稱和描述符。
4.JVM 類加載
① 類加載過程
?對于一個(gè)類來說,它的生命周期是這樣的:
1) 加載
????????“加載
”
(
Loading
)階段是整個(gè)
“
類加載
”
(
Class Loading
)過程中的一個(gè)階段,它和類加載
Class Loading 是不同的,一個(gè)是加載
Loading
另一個(gè)是類加載
Class Loading
,所以不要把二者搞混了。
在加載
Loading
階段,
Java
虛擬機(jī)需要完成以下
三件事情
:
1
)通過一個(gè)類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流。
2
)將這個(gè)字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)。
3
)在內(nèi)存中生成一個(gè)代表這個(gè)類的
java.lang.Class
對象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問入口。
2) 驗(yàn)證
????????驗(yàn)證是連接階段的第一步,這一階段的目的是確保Class
文件的字節(jié) 流中包含的信息符合《
Java虛擬機(jī) 規(guī)范》的全部約束要求,保證這些信 息被當(dāng)作代碼運(yùn)行后不會危害虛擬機(jī)自身的安全。
????????驗(yàn)證選項(xiàng): 文件格式驗(yàn)證? ? 字節(jié)碼驗(yàn)證? ? 符號引用驗(yàn)證...
3) 準(zhǔn)備
????????準(zhǔn)備階段是正式為類中定義的變量(即靜態(tài)變量,被static
修飾的變量)分配內(nèi)存并設(shè)置類變量初始值 的階段。
? 比如此時(shí)有這樣一行代碼:
????????public static int value = 123;
????????它是初始化 value
的
int
值為
0
,而非
123
。
4) 解析
?????????解析階段是 Java
虛擬機(jī)將常量池內(nèi)的符號引用替換為直接引用的過程,也就是初始化常量的過程。
5) 初始化
????????初始化階段,Java
虛擬機(jī)真正開始執(zhí)行類中編寫的
Java
程序代碼,將主導(dǎo)權(quán)移交給應(yīng)用程序。初始化階段就是執(zhí)行類構(gòu)造器方法的過程。
② 雙親委派模型
????????如果一個(gè)類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個(gè)類,而是把這個(gè)請求委派給父 類加載器去完成,每一個(gè)層次的類加載器都是如此,因此所有的加載請求最 終都應(yīng)該傳送到最頂層的啟 動類加載器中,只有當(dāng)父加載器反饋?zhàn)约簾o 法完成這個(gè)加載請求(它的搜索范圍中沒有找到所需的類) 時(shí),子加載器才會嘗試自己去完成加載。
雙親委派模型的優(yōu)點(diǎn)
????????1. 避免重復(fù)加載類:比如
A
類和
B
類都有一個(gè)父類
C
類,那么當(dāng)
A
啟動時(shí)就會將
C
類加載起來,那 么在 B
類進(jìn)行加載時(shí)就不需要在重復(fù)加載
C
類了。
????????2. 安全性:使用雙親委派模型也可以保證了
Java
的核心
API
不被篡改,如果沒有使用雙親委派模 型,而是每個(gè)類加載器加載自己的話就會出現(xiàn)一些問題,比如我們編寫一個(gè)稱為 java.lang.Object 類的話,那么程序運(yùn)行的時(shí)候,系統(tǒng)就會出現(xiàn)多個(gè)不同的 Object
類,而有些
Object
類又是用戶 自己提供的因此安全性就不能得到保證了。
柚子快報(bào)邀請碼778899分享:JVM的工作流程
參考鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。