自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們一起聊聊JVM是如何執(zhí)行Java程序的

開(kāi)發(fā) 前端
類加載系統(tǒng)目的很明確,就是將字節(jié)碼文件中的二進(jìn)制數(shù)據(jù)準(zhǔn)確地加載到JVM,從Class文件加載到內(nèi)存 & 對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)、轉(zhuǎn)換解析和初始化,最終形成可被虛擬機(jī)直接使用的Java使用類型。

前言

如果你對(duì)JVM一知半解,如果你想了解JVM的工作流程,如果你知道一些JVM面試題卻無(wú)法將知識(shí)點(diǎn)串聯(lián)起來(lái),那么這篇文章非常適合你。

從面試題說(shuō)起

這些面試題Javaer們應(yīng)該都很熟悉,但是你知道這些面試題的背后嗎?

  • 你知道類加載機(jī)制嗎?
  • 什么是雙親委派機(jī)制?
  • 介紹一下JVM內(nèi)存區(qū)域劃分
  • 堆為什么要分代設(shè)計(jì)?
  • 什么是內(nèi)存的擔(dān)保機(jī)制?
  • 為什么Eden:S0:S1 比例是8:1:1?
  • 描述一下對(duì)象內(nèi)存分配過(guò)程
  • 如何判斷對(duì)象已死?
  • 講一講內(nèi)存模型?
  • 常用的JVM調(diào)優(yōu)參數(shù)有哪些?
  • 常用的垃圾回收算法有哪些?
  • 常用的垃圾收集器有哪些?
  • ......

圖片圖片

如果你總是背了又忘,忘了又背,歸根結(jié)底,還是對(duì)JVM沒(méi)有一個(gè)系統(tǒng)的認(rèn)識(shí)。

那么希望通過(guò)這篇文章,可以為你構(gòu)建一個(gè)連貫的JVM框架。

JVM做了哪些事?

眾所周知,高級(jí)編程語(yǔ)言編寫的程序,最終要轉(zhuǎn)化為機(jī)器碼,才可以在計(jì)算機(jī)上運(yùn)行。

圖片圖片

“翻譯”的工作

我們?cè)诰帉懲暌欢蜫ava代碼后,如果想要運(yùn)行它,需要通過(guò)Java編譯器,將其編譯為JVM認(rèn)識(shí)的字節(jié)碼文件。

圖片圖片

然后執(zhí)行Java命令,這段代碼就會(huì)通過(guò)JVM運(yùn)行。

圖片圖片

不僅僅“翻譯”

在這個(gè)過(guò)程中,JVM就充當(dāng)了轉(zhuǎn)換的角色,負(fù)責(zé)將字節(jié)碼,翻譯成對(duì)應(yīng)平臺(tái)上的機(jī)器指令。這樣的話,Java程序就可以在任何安裝了JVM的平臺(tái)上運(yùn)行。這就是Java語(yǔ)言一次編寫到處運(yùn)行的跨平臺(tái)特性。

圖片圖片

翻譯字節(jié)碼的工作,是由JVM的執(zhí)行引擎完成。

在將字節(jié)碼翻譯為機(jī)器指令之前,JVM還有一個(gè)非常重要的工作,那就是將字節(jié)碼文件中的二進(jìn)制數(shù)據(jù)準(zhǔn)確的加載到JVM中。這個(gè)工作是由JVM的類加載系統(tǒng)完成,

另外,為了在運(yùn)行時(shí)方便管理內(nèi)存,JVM定義了一個(gè)專門的區(qū)域,也就是大名鼎鼎的運(yùn)行時(shí)數(shù)據(jù)區(qū)。

圖片圖片

所以,類加載系統(tǒng)、運(yùn)行時(shí)數(shù)據(jù)區(qū)、執(zhí)行引擎,就構(gòu)成了JVM平臺(tái)。

接下來(lái),看一下它們是如何工作的。

在這之前,要對(duì)字節(jié)碼現(xiàn)有一個(gè)認(rèn)識(shí),畢竟它貫穿了Java代碼運(yùn)行的整個(gè)流程。

Java虛擬機(jī)對(duì)Java編程語(yǔ)言一無(wú)所知,只知道一種特定的二進(jìn)制格式,即類文件格式。類文件包含Java虛擬機(jī)指令(或字節(jié)碼)和符號(hào)表,以及其他輔助信息。

JVM 各部件如何協(xié)同工作?

類加載器先工作

類加載系統(tǒng)目的很明確,就是將字節(jié)碼文件中的二進(jìn)制數(shù)據(jù)準(zhǔn)確地加載到JVM,從Class文件加載到內(nèi)存 & 對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)、轉(zhuǎn)換解析和初始化,最終形成可被虛擬機(jī)直接使用的Java使用類型

執(zhí)行Java命令后,Java虛擬機(jī)啟動(dòng),類加載系統(tǒng)就開(kāi)始工作了。

圖片圖片

類加載系統(tǒng)首先會(huì)讀取指定的類文件,并遵循雙親委派機(jī)制進(jìn)行加載。

圖片圖片

然后將文件中的常量池、字段、方法和指令等數(shù)據(jù)加載到JVM內(nèi)存的共享區(qū)域方法區(qū)中。

圖片圖片

然后對(duì)其進(jìn)行驗(yàn)證,目的是為了確保類的正確性。比如版本號(hào)為52或更高時(shí),不應(yīng)該存在這個(gè)版本不支持的指令。

圖片圖片

或者標(biāo)識(shí)類文件的魔術(shù)數(shù)字是不是cafebabe,這些完整性的檢查和約束都是非常有必要,就像我們自己開(kāi)發(fā)的應(yīng)用,也不可能隨便讓別人訪問(wèn)一樣。

圖片圖片

驗(yàn)證完成后,在方法區(qū)為類的靜態(tài)變量分配內(nèi)存并設(shè)置默認(rèn)值。

圖片圖片

緊接著,將常量池中表示對(duì)象的符號(hào)引用,指向到實(shí)際的內(nèi)存地址,也就是直接引用。

圖片圖片

什么是符號(hào)引用呢?

符號(hào)引用是常量池中的類、方法、字段等指向的目標(biāo)在字節(jié)碼文件中的靜態(tài)表示,當(dāng)JVM運(yùn)行時(shí),需要將目標(biāo)的靜態(tài)表示轉(zhuǎn)換成實(shí)際的內(nèi)存指針,也就是直接引用。在這個(gè)例子中,如果JVM需要加載Object這個(gè)類,它會(huì)查找常量池中的#3(Class類型,指向#27),然后解析#27中的字符串java/lang/Object/為實(shí)際的類文件路徑,并加載這個(gè)類。

最后執(zhí)行靜態(tài)代碼塊,為靜態(tài)變量設(shè)置初始值,類加載工作就算完成了。

整個(gè)加載過(guò)程就是面試被經(jīng)常問(wèn)到的類加載機(jī)制。

圖片圖片

那么問(wèn)題來(lái)了:靜態(tài)變量為什么要先設(shè)置默認(rèn)值,再設(shè)置初始值,知道的評(píng)論區(qū)留言。

執(zhí)行引擎開(kāi)始工作

執(zhí)行引擎工作模式

靜態(tài)代碼塊被執(zhí)行時(shí),執(zhí)行引擎就會(huì)處理這些指令。執(zhí)行引擎有兩種工作模式:

  • 解釋執(zhí)行
  • 即時(shí)編譯

解釋執(zhí)行就是每次執(zhí)行都會(huì)逐行解釋字節(jié)碼指令

圖片圖片

即時(shí)編譯是將熱點(diǎn)代碼,編譯成當(dāng)前平臺(tái)的機(jī)器碼,并緩存下次就可以直接執(zhí)行機(jī)器碼,這樣就可以提高執(zhí)行效率。

圖片圖片

JVM通常采用解釋器與即時(shí)編譯器并存的混合模式。在程序啟動(dòng)時(shí),解釋器可以立即發(fā)揮作用,省去編譯時(shí)間;隨著程序運(yùn)行時(shí)間的推移,JIT編譯器逐漸發(fā)揮作用,將越來(lái)越多的熱點(diǎn)代碼編譯為本地機(jī)器碼,以提高執(zhí)行效率。

Main方法什么時(shí)候被執(zhí)行?

靜態(tài)代碼塊執(zhí)行完成后,JVM會(huì)繼續(xù)調(diào)用main方法。如果執(zhí)行Java命令的字節(jié)碼文件中沒(méi)有main方法,JVM就會(huì)報(bào)錯(cuò),這個(gè)是JVM規(guī)范。

圖片圖片

運(yùn)行時(shí)數(shù)據(jù)區(qū)域開(kāi)始工作

執(zhí)行引擎工作期間,會(huì)和運(yùn)行時(shí)數(shù)據(jù)區(qū)域有大量的交互。

線程私有的空間

調(diào)用main方法時(shí),會(huì)創(chuàng)建一個(gè)線程并在運(yùn)行時(shí)數(shù)據(jù)區(qū)中分配線程私有的空間:棧幀以及程序計(jì)數(shù)器。

圖片圖片

程序計(jì)數(shù)器初始時(shí)會(huì)指向第一條指令, 然后隨著指令的執(zhí)行而遞增。

圖片圖片

執(zhí)行靜態(tài)變量賦值的指令時(shí),會(huì)把整數(shù)推送到棧幀中的操作數(shù)棧,隨后賦值給靜態(tài)變量。

圖片圖片

在執(zhí)行創(chuàng)建一個(gè)Object實(shí)例的指令時(shí),如果Object Class未被加載,類加載器會(huì)啟動(dòng)加載過(guò)程。然后在堆中分配一塊內(nèi)存并初始化實(shí)例。

圖片圖片

大名鼎鼎的堆內(nèi)存

分配內(nèi)存這個(gè)過(guò)程,就涉及到“堆內(nèi)存分代設(shè)計(jì)”、“對(duì)象內(nèi)存分配過(guò)程”、“內(nèi)存分配方式”等知識(shí)點(diǎn)了。

圖片圖片

如果對(duì)象過(guò)多導(dǎo)致空間不足,JVM就會(huì)通過(guò)垃圾回收來(lái)釋放一些空間。“如何確定對(duì)象是垃圾”、“使用哪個(gè)垃圾回收器”、“用了什么回收算法”就需要我們?nèi)チ私狻?/p>

圖片圖片

實(shí)例初始化后,會(huì)將對(duì)象的引用存儲(chǔ)到局部變量表中。這樣的話,線程就可以通過(guò)引用訪問(wèn)到該對(duì)象。

圖片圖片

就這么一直工作

后續(xù)的代碼會(huì)延續(xù)這個(gè)流程,該加載類的加載類、該翻譯指令的翻譯、該分配內(nèi)存的分配、該回收垃圾的回收,直到Java虛擬機(jī)停止工作。

圖片圖片

責(zé)任編輯:武曉燕 來(lái)源: Hi程序員
相關(guān)推薦

2023-07-14 12:28:07

JVM優(yōu)化操作

2022-08-01 07:57:03

數(shù)組操作內(nèi)存

2023-12-29 08:29:15

QPS系統(tǒng)應(yīng)用

2023-03-26 00:00:01

應(yīng)用程序LLM策略

2025-03-27 02:00:00

SPIJava接口

2022-07-29 08:17:46

Java對(duì)象內(nèi)存

2022-12-06 08:12:11

Java關(guān)鍵字

2023-04-03 00:09:13

2024-09-09 00:00:00

編寫技術(shù)文檔

2024-11-27 16:07:45

2024-09-30 09:33:31

2022-10-08 00:00:05

SQL機(jī)制結(jié)構(gòu)

2023-04-26 07:30:00

promptUI非結(jié)構(gòu)化

2023-08-04 08:20:56

DockerfileDocker工具

2022-05-24 08:21:16

數(shù)據(jù)安全API

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2023-09-10 21:42:31

2023-06-30 08:18:51

敏捷開(kāi)發(fā)模式

2021-08-27 07:06:10

IOJava抽象

2024-02-20 21:34:16

循環(huán)GolangGo
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)