虛擬機(一)-JVM執(zhí)行java代碼流程淺析

文章為作者原創(chuàng)坪稽,轉(zhuǎn)載請注明出處曼玩,多謝配合!

本文打算針對jvm執(zhí)行java代碼流程做個簡單的梳理窒百。對jvm有個大框架的認識黍判。

首先通過一張整體流程圖來宏觀了解下jvm執(zhí)行java代碼流程:


下面拆解開來分別進行解讀:

一.編譯

java編譯器:比如javac (sun公司編譯器,jdk默認自帶的編譯器)

java編譯器的作用:讀入java源代碼篙梢,進行語法校驗顷帖,通過后生成中間代碼即字節(jié)碼(.class文件)。字節(jié)碼文件是一種和任何具體機器環(huán)境及操作系統(tǒng)環(huán)境無關(guān)的中間代碼,它是一種二進制文件窟她。編譯器編譯生成與平臺無關(guān)的字節(jié)碼文件后,提供給 JVM (Java虛擬機)執(zhí)行蔼水。

另外需要注意的是:

(1)編譯器編譯一個java文件震糖,涉及到的對象都會單獨生成一一對應(yīng)的.class文件,有多少對象生成多少個趴腋。

(2)字節(jié)碼 ≠ 機器碼 吊说,字節(jié)碼是虛擬機認識的碼,機器碼是操作系統(tǒng)認識的碼优炬。
C/C++在編譯的時候直接編譯成機器碼颁井,而java是先編譯成字節(jié)碼,再由虛擬機轉(zhuǎn)換為機器碼蠢护。
詳細了解字節(jié)碼雅宾,可參考:http://www.importnew.com/24088.html

(3)為什么java編譯出來的是字節(jié)碼而不是機器碼?
最主要的目的是跨平臺葵硕,為了實現(xiàn)跨平臺眉抬,就決定了不能像 c,c++ 那樣直接把源代碼編譯成可執(zhí)行文件懈凹,因為不同cpu蜀变,不同操作系 統(tǒng)的指令封裝格式是不一樣的。java編譯成的字節(jié)碼文件.class介评,與硬件和操作系統(tǒng)無關(guān)库北,這是跨平臺基礎(chǔ),然后具體執(zhí)行们陆,再用各自平臺解釋器寒瓦,解釋成本地機器碼。java是一種編譯+解釋的語言棒掠。

二.類裝載器如何把.class文件裝載到內(nèi)存

在編譯期孵构,所有的*.java文件被編譯成.class文件。在運行期烟很,class文件只有被加載到j(luò)vm內(nèi)存中才能運行颈墅。這個裝載工作是由類裝載器完成的。實質(zhì)就是把class文件從硬盤讀取到內(nèi)存中雾袱,并對數(shù)據(jù)進行驗證恤筛、準備、解析芹橡、初始化毒坛,最終形成可以被jvm直接使用的java類型。
1.裝載方式以及裝載器介紹:
類裝載方式,有兩種
(1)隱式裝載煎殷, 程序在運行過程中當碰到通過new 等方式生成對象時屯伞,隱式調(diào)用類裝載器加載對應(yīng)的類到j(luò)vm中,
(2)顯式裝載豪直, 通過class.forname()等方法劣摇,顯式加載需要的類。

Java類的加載是動態(tài)的弓乙,它并不會一次性將所有類全部加載后再運行末融,而是保證程序運行的基礎(chǔ)類(像是基類)完全加載到j(luò)vm中,至于其他類暇韧,則在需要的時候才加載勾习。這當然就是為了節(jié)省內(nèi)存開銷。

Java的類加載器有三個懈玻,對應(yīng)Java的三種類:(java中的類大致分為三種: 1.系統(tǒng)類 2.擴展類 3.由程序員自定義的類 )

Bootstrap Loader  // 負責(zé)加載系統(tǒng)類 (指的是內(nèi)置類巧婶,像是String,對應(yīng)于C#中的System類和C/C++標準庫中的類)
       |
     - - ExtClassLoader   // 負責(zé)加載擴展類(就是繼承類和實現(xiàn)類)
                     |
                  - - AppClassLoader   // 負責(zé)加載應(yīng)用類(程序員自定義的類)

  jdk源碼角度的加載過程不做過多解釋了酪刀,有興趣的可以參看:[https://blog.csdn.net/architect0719/article/details/50411545](https://blog.csdn.net/architect0719/article/details/50411545)

2.JVM類加載機制

?全盤負責(zé):當一個類加載器負責(zé)加載某個Class時粹舵,該Class所依賴的和引用的其他Class也將由該類加載器負責(zé)載入,除非顯示使用另外一個類加載器來載入骂倘。

?雙親委派:雙親委派模型的工作流程是:如果一個類加載器收到了類加載的請求眼滤,它首先不會自己去嘗試加載這個類,而是把請求委托給父加載器去完成历涝,依次向上诅需,因此,所有的類加載請求最終都應(yīng)該被傳遞到頂層的啟動類加載器中荧库,只有當父加載器在它的搜索范圍中沒有找到所需的類時堰塌,即無法完成該加載,子加載器才會嘗試自己去加載該類分衫。

?緩存機制:緩存機制將會保證所有加載過的Class都會被緩存场刑,當程序中需要使用某個Class時,類加載器先從緩存區(qū)尋找該Class蚪战,只有緩存區(qū)不存在牵现,系統(tǒng)才會讀取該類對應(yīng)的二進制數(shù)據(jù),并將其轉(zhuǎn)換成Class對象邀桑,存入緩存區(qū)瞎疼。這就是為什么修改了Class后,必須重啟JVM壁畸,程序的修改才會生效贼急。

  1. 類加載的過程:

類裝載器就是尋找類或接口字節(jié)碼文件進行解析并構(gòu)造JVM內(nèi)部對象表示的組件茅茂,在java中類裝載器把一個類裝入JVM,經(jīng)過以下步驟:

加載太抓、驗證空闲、準備、解析走敌、初始化五個階段进副。

加載:
1)通過一個類的全限定名來獲取定義此類的的二進制字節(jié)流
2)將這個字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)運行時的數(shù)據(jù)結(jié)構(gòu)
3)在內(nèi)存的堆區(qū)生成一個java.lang.Class對象,作為方法區(qū)這個類的各種數(shù)據(jù)的訪問入口悔常。

驗證:確保Class文件中的字節(jié)流中的包含信息符合jvm的要求,并且不會虛擬機自身的安全给赞。

準備:在方法區(qū)給靜態(tài)的類變量分配內(nèi)存机打,并設(shè)置初始值。實例變量(未被static修飾的類變量)將會在對象實例化時片迅,隨對象一起分配到j(luò)ava堆中残邀。

解析:將符號引用轉(zhuǎn)成直接引用。

初始化:對靜態(tài)變量和靜態(tài)代碼塊執(zhí)行初始化工作芍锦。

三文捶、一個類在jvm內(nèi)存中數(shù)據(jù)是如何被管理的

首先我們知道壁熄,jvm的一個重要職責(zé)就是管理好從計算機內(nèi)存空間申請來的一畝三分地,運行時數(shù)據(jù)區(qū)常見劃分方式為:

1)程序計數(shù)器:一個指針空免,指向執(zhí)行引擎正在執(zhí)行的指令的地址;
2)虛擬機棧:局部變量的基本數(shù)據(jù)類型和引用盆耽;
3)堆:引用的對象實體蹋砚、成員變量全部存儲與堆中(包括基本數(shù)據(jù)類型,引用和引用的對象實體)摄杂;
4)方法區(qū):加載類的信息坝咐、靜態(tài)變量;里面包含了常量池析恢,常量池里放常量以及串池墨坚;
5)本地方法棧:它的存儲跟虛擬機棧類似,只是針對的是native方法映挂。

(其中堆和方法區(qū)是線程共享的泽篮,其余的則是線程隔離的)

有一個小結(jié)論:
局部變量的基本數(shù)據(jù)類型和引用存儲于棧中,引用的對象實體存儲于堆中袖肥。
——因為它們屬于方法中的變量咪辱,生命周期隨方法而結(jié)束。

成員變量全部存儲與堆中(包括基本數(shù)據(jù)類型椎组,引用和引用的對象實體)
——因為它們屬于類油狂,類對象終究是要被new出來使用的。

jvm的gc針對的主要就是堆區(qū):gc的詳細分析參考之前的文章:http://www.reibang.com/p/220d6827be0d

四.執(zhí)行引擎

1.執(zhí)行引擎是干嘛的
前面我們了解了,類裝載器裝載編譯后的字節(jié)碼专筷,并加載到運行時數(shù)據(jù)區(qū)弱贼,但是我們知道,Java字節(jié)碼是用一種人類可以讀懂的語言編寫的磷蛹,而不是用機器可以直接執(zhí)行的語言吮旅,所以需要由執(zhí)行引擎執(zhí)行這些字節(jié)碼,轉(zhuǎn)換生成由機器碼組成的可被jvm執(zhí)行的文件味咳。

執(zhí)行引擎找到入口main方法來執(zhí)行其中的字節(jié)碼庇勃。

2.轉(zhuǎn)換方式
(1)解釋器:一條一條地讀取,解釋并且執(zhí)行字節(jié)碼指令槽驶。因為它一條一條地解釋和執(zhí)行指令责嚷,所以它可以很快地解釋字節(jié)碼,但是執(zhí)行起來會比較慢掂铐。這是解釋執(zhí)行的語言的一個缺點罕拂。字節(jié)碼這種“語言”基本來說是解釋執(zhí)行的。

(2)即時(Just-In-Time)編譯器:Oracle Hotspot VM使用一種JIT編譯器全陨,即時編譯器被引入用來彌補解釋器的缺點爆班。執(zhí)行引擎首先按照解釋執(zhí)行的方式來執(zhí)行,然后在合適的時候辱姨,即時編譯器把整段字節(jié)碼編譯成本地代碼柿菩。然后,執(zhí)行引擎就沒有必要再去解釋執(zhí)行方法了雨涛,它可以直接通過本地代碼去執(zhí)行它碗旅。執(zhí)行本地代碼比一條一條進行解釋執(zhí)行的速度快很多。編譯后的代碼可以執(zhí)行的很快镜悉,因為本地代碼是保存在緩存里的祟辟。不過,用JIT編譯器來編譯代碼所花的時間要比用解釋器去一條條解釋執(zhí)行花的時間要多侣肄。因此旧困,如果代碼只被執(zhí)行一次的話,那么最好還是解釋執(zhí)行而不是編譯后再執(zhí)行稼锅。

因此吼具,內(nèi)置了JIT編譯器的JVM都會檢查方法的執(zhí)行頻率,如果一個方法的執(zhí)行頻率超過一個特定的值的話矩距,那么這個方法就會被編譯成本地代碼拗盒。

具體做法:

每個方法被調(diào)用一次就給這個方法計數(shù)加1。

那些方法的被調(diào)用計數(shù)越多锥债,JVM就優(yōu)先翻譯成機器碼(使用JIT編譯器)陡蝇,當然少的可能在執(zhí)行到的時候再翻譯(使用解釋器)

(3)AOT(Ahead-Of-Time)編譯器 IBM 在IBM JDK 6里不僅引入了JIT編譯器痊臭,它同時還引入了AOT(Ahead-Of-Time)編譯器。它使得多個JVM可以通過共享緩存來共享編譯過的本地代碼登夫。簡而言之广匙,通過AOT編譯器編譯過的代碼可以直接被其他JVM使用。除此之外恼策,IBM JVM通過使用AOT編譯器來提前把代碼編譯器成JXE(Java EXecutable)文件格式來提供一種更加快速的執(zhí)行方式鸦致。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者涣楷。
  • 序言:七十年代末分唾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子狮斗,更是在濱河造成了極大的恐慌鳍寂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件情龄,死亡現(xiàn)場離奇詭異,居然都是意外死亡捍壤,警方通過查閱死者的電腦和手機骤视,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鹃觉,“玉大人专酗,你說我怎么就攤上這事〉辽龋” “怎么了祷肯?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疗隶。 經(jīng)常有香客問我佑笋,道長,這世上最難降的妖魔是什么斑鼻? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任蒋纬,我火速辦了婚禮,結(jié)果婚禮上坚弱,老公的妹妹穿的比我還像新娘蜀备。我一直安慰自己,他們只是感情好荒叶,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布碾阁。 她就那樣靜靜地躺著,像睡著了一般些楣。 火紅的嫁衣襯著肌膚如雪脂凶。 梳的紋絲不亂的頭發(fā)上宪睹,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音艰猬,去河邊找鬼横堡。 笑死,一個胖子當著我的面吹牛冠桃,可吹牛的內(nèi)容都是我干的命贴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼食听,長吁一口氣:“原來是場噩夢啊……” “哼胸蛛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起樱报,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤葬项,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后迹蛤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體民珍,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年盗飒,在試婚紗的時候發(fā)現(xiàn)自己被綠了嚷量。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡逆趣,死狀恐怖蝶溶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宣渗,我是刑警寧澤抖所,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站痕囱,受9級特大地震影響田轧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鞍恢,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一涯鲁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧有序,春花似錦抹腿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至盅称,卻和暖如春肩祥,著一層夾襖步出監(jiān)牢的瞬間后室,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工混狠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留岸霹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓将饺,卻偏偏與公主長得像贡避,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子予弧,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355