JVM體系架構(gòu)

JVM是什么

JVM全稱(chēng)Java Virtual Machine(Java虛擬機(jī)),是一個(gè)虛構(gòu)出來(lái)的計(jì)算機(jī),它屏蔽了與具體操作系統(tǒng)平臺(tái)相關(guān)的信息,使得Java程序只需生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼,ByteCode), 就可以在多種平臺(tái)上不加修改地運(yùn)行。這背后其實(shí)就是JVM把字節(jié)碼翻譯成具體平臺(tái)上的機(jī)器指令,從而實(shí)現(xiàn)“一次編寫(xiě),到處運(yùn)行(Write Once, Run Anywhere)”。

JVM架構(gòu)圖

JVM-Architecture.png

JVM工作機(jī)制

如上面的架構(gòu)圖所示,JVM分成四個(gè)主要的子系統(tǒng):

  1. 類(lèi)加載器
  2. 運(yùn)行時(shí)數(shù)據(jù)區(qū)
  3. 執(zhí)行引擎
  4. 本地方法調(diào)用

類(lèi)加載器

Java的動(dòng)態(tài)類(lèi)加載功能由類(lèi)加載器子系統(tǒng)處理。它加載,鏈接,并在類(lèi)運(yùn)行時(shí)第一次引用類(lèi)時(shí)初始化類(lèi)文件,而不是編譯時(shí)。

1.1 加載

通過(guò)類(lèi)加載器實(shí)現(xiàn)類(lèi)的加載動(dòng)作,絕大部分Java程序都會(huì)使用到以下三種系統(tǒng)提供的類(lèi)加載器:

  1. 啟動(dòng)類(lèi)加載器(Bootstrap ClassLoader)
  2. 擴(kuò)展類(lèi)加載器(Extension ClassLoader)
  3. 應(yīng)用程序類(lèi)加載器(Application ClassLoader)

上面的類(lèi)加載器將在加載類(lèi)文件時(shí)遵循委托層次結(jié)構(gòu)算法。

1.2 鏈接

  • 驗(yàn)證 確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)自身的安全
  • 準(zhǔn)備 正式為類(lèi)變量分配內(nèi)存并設(shè)置初始值的階段,這些變量所使用的內(nèi)存都將在方法區(qū)中進(jìn)行分配
  • 解析 虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程

1.3 初始化

這是類(lèi)加載的最后階段,為所有的變量分配原始值,并執(zhí)行靜態(tài)代碼塊

運(yùn)行時(shí)數(shù)據(jù)區(qū)

Java虛擬機(jī)在運(yùn)行程序的過(guò)程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)。這些區(qū)域都有各自的用途,以及創(chuàng)建和銷(xiāo)毀的時(shí)間,有的區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,有的區(qū)域則依賴用戶線程的啟動(dòng)和結(jié)束而建立和銷(xiāo)毀。

程序計(jì)數(shù)器

一塊較小的內(nèi)存空間,可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼行號(hào)指示器

Java虛擬機(jī)棧

Java虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型,每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)站幀(Stack Frame)用于存儲(chǔ)局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息。每個(gè)方法從調(diào)用到執(zhí)行完成的過(guò)程,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過(guò)程。

本地方法棧

本地方法棧與虛擬機(jī)棧發(fā)揮的作用類(lèi)似,虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機(jī)使用的Native方法服務(wù)。

Java堆

Java堆是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊。Java堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建。此內(nèi)存區(qū)域的唯一目的就是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都在這里分配內(nèi)存。

Java堆是垃圾收集器管理的主要區(qū)域,因此很多時(shí)候也稱(chēng)作GC堆。

方法區(qū)

與Java堆一樣,是各個(gè)線程共享的內(nèi)存區(qū)域,它用于存儲(chǔ)已被虛擬機(jī)加載的類(lèi)信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。

執(zhí)行引擎

執(zhí)行通過(guò)類(lèi)加載器分配給運(yùn)行時(shí)數(shù)據(jù)區(qū)的字節(jié)碼,并將這些字節(jié)碼轉(zhuǎn)換成JVM虛擬機(jī)更容易執(zhí)行的語(yǔ)言。主要有三個(gè)子組件。

解釋器

負(fù)責(zé)讀取字節(jié)碼并順序的執(zhí)行。缺點(diǎn)是當(dāng)一個(gè)方法被多次調(diào)用時(shí),每次都需要新的解釋。

JIT(Just In Time)編譯器

抵消了解釋器執(zhí)行緩慢的缺點(diǎn)。JIT編譯器同時(shí)編譯字節(jié)碼的重復(fù)部分,總而減少編譯所需的總時(shí)間。從而提高性能。

  1. 中間代碼生成器 負(fù)責(zé)生成中間代碼
  2. 代碼優(yōu)化器 負(fù)責(zé)優(yōu)化上面生成的中間代碼
  3. 目標(biāo)代碼生成器 負(fù)責(zé)生成機(jī)器代碼或本機(jī)代碼
  4. Profiler 一個(gè)特殊組件,負(fù)責(zé)查找熱點(diǎn),即是否被多次調(diào)用

垃圾收集器

收集和刪除未引用的對(duì)象來(lái)釋放內(nèi)存??梢酝ㄟ^(guò)調(diào)用觸發(fā)垃圾收集System.gc(),但不保證執(zhí)行。

本地方法接口

JNI與本地方法庫(kù)交互,并提供執(zhí)行引擎所需的本地庫(kù)

本地方法庫(kù)

執(zhí)行引擎所需要的本地庫(kù)的集合

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 這篇文章是我之前翻閱了不少的書(shū)籍以及從網(wǎng)絡(luò)上收集的一些資料的整理,因此不免有一些不準(zhǔn)確的地方,同時(shí)不同JDK版本的...
    高廣超閱讀 16,059評(píng)論 3 83
  • 內(nèi)存溢出和內(nèi)存泄漏的區(qū)別 內(nèi)存溢出:out of memory,是指程序在申請(qǐng)內(nèi)存時(shí),沒(méi)有足夠的內(nèi)存空間供其使用,...
    Aimerwhy閱讀 807評(píng)論 0 1
  • 第二部分 自動(dòng)內(nèi)存管理機(jī)制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運(yùn)行數(shù)據(jù)區(qū)域 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,294評(píng)論 0 2
  • 《深入理解Java虛擬機(jī)》筆記_第一遍 先取看完這本書(shū)(JVM)后必須掌握的部分。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,476評(píng)論 1 34
  • 像云朵 緩慢爬過(guò)河流 白羊溫順的看了一眼 九月 繼續(xù)低頭 啃草 并不準(zhǔn)備 為詩(shī)經(jīng)里的佳人讓出 在水一方 ...
    楊昊田閱讀 1,172評(píng)論 28 31

友情鏈接更多精彩內(nèi)容