Java虛擬機(jī)是一臺(tái)執(zhí)行Java字節(jié)碼的虛擬計(jì)算機(jī),它擁有獨(dú)立的運(yùn)行機(jī)制前酿,其運(yùn)行的Java字節(jié)碼也未必由Java語言編譯而成患雏。
Java技術(shù)的核心就是Java虛擬機(jī)(JVM,Java Virtual Machine),因?yàn)樗械腏ava程序都運(yùn)行在Java虛擬機(jī)內(nèi)部。
- 作用
Java虛擬機(jī)就是二進(jìn)制字節(jié)碼的運(yùn)行環(huán)境罢维,負(fù)責(zé)裝載字節(jié)碼到其內(nèi)部淹仑,編譯為對(duì)應(yīng)平臺(tái)上的機(jī)器指令執(zhí)行。每一條Java指令肺孵,Java虛擬機(jī)規(guī)范中都有詳細(xì)定義匀借,如怎么取操作數(shù),怎么處理操作數(shù)平窘,處理結(jié)果放在哪里吓肋。 - 特點(diǎn)
?一次編譯,到處運(yùn)行瑰艘。
?自動(dòng)內(nèi)存管理是鬼。
?自動(dòng)垃圾回收。
JVM是運(yùn)行在操作系統(tǒng)之上的紫新,它與硬件沒有直接的交互均蜜。不同的操作系統(tǒng)裝的JVM是有區(qū)別的。
類裝載器子系統(tǒng)將字節(jié)碼文件加載到內(nèi)存中生成Class對(duì)象然后在執(zhí)行引擎解釋運(yùn)行弊琴。這個(gè)過程中涉及到加載->鏈接->初始化兆龙。在內(nèi)存中多線程共享堆和方法區(qū)杖爽。每個(gè)線程獨(dú)有一份Java虛擬機(jī)棧敲董,本地方法棧和程序計(jì)數(shù)器。
1程序計(jì)數(shù)器:每個(gè)線程一塊慰安,指向當(dāng)前線程正在執(zhí)行的字節(jié)碼代碼的行號(hào)腋寨。如果當(dāng)前線程執(zhí)行的是navtive方法,則其值為null化焕。
2Java虛擬機(jī)棧:線程私有萄窜,每個(gè)線程對(duì)應(yīng)一個(gè)Java虛擬機(jī)棧,其生命周期與線程同進(jìn)同退撒桨。每個(gè)Java方法在被調(diào)用的時(shí)候都會(huì)創(chuàng)建一個(gè)棧幀查刻,并入棧。一旦完成調(diào)用凤类,則出棧穗泵。所有的棧幀都出棧后,線程也就完成了使命谜疤。
3本地方法棧:功能與Java虛擬機(jī)棧十分相同佃延。區(qū)別在于现诀,本地方法棧為虛擬機(jī)使用到的native方法服務(wù)。
4堆:堆是JVM內(nèi)存占用最大履肃,管理最復(fù)雜的一個(gè)區(qū)域仔沿。堆是所有線程共享的一塊區(qū)域,主要用來存放對(duì)象和數(shù)組尺棋。在Java虛擬機(jī)規(guī)范中有描述:所有的對(duì)象實(shí)例和數(shù)組都要在堆上分配封锉。但是隨著JIT(JUST-IN-TIME)編譯器的發(fā)展與逃逸分析技術(shù)的逐漸成熟,并不是所有對(duì)象都只在堆上分配了膘螟,比如:隨著逃逸分析技術(shù)的逐漸成熟烘浦,在即使能被回收的對(duì)象也有肯能會(huì)在虛擬機(jī)棧上分配。
1.7后萍鲸,字符串常量池從永久代中剝離出來闷叉,存放在堆中。堆有自己進(jìn)一步的內(nèi)存分塊劃分脊阴。
5執(zhí)行引擎:分為解釋器握侧、JIT編譯器(后端編譯器)【編譯反復(fù)執(zhí)行的熱點(diǎn)代碼】和垃圾回收器。操作系統(tǒng)只能識(shí)別機(jī)器指令嘿期,但是字節(jié)碼指令不等同于機(jī)器指令品擎。要想字節(jié)碼文件能夠解釋執(zhí)行就需要借助執(zhí)行引擎,把高級(jí)語言翻譯成機(jī)器語言备徐。
Java代碼的執(zhí)行流程
JVM的架構(gòu)模型
Java編譯器輸入的指令流基本上是一種基于棧的指令集架構(gòu)萄传。
基于棧式架構(gòu)的特點(diǎn):
?設(shè)計(jì)和實(shí)現(xiàn)簡(jiǎn)單(Java程序的運(yùn)行通過方法實(shí)現(xiàn),每執(zhí)行一個(gè)方法可以理解為一個(gè)入棧操作蜜猾,棧頂就是當(dāng)前正在執(zhí)行的方法秀菱,方法執(zhí)行完做一個(gè)出棧的操作就可以了),適用于資源受限的系統(tǒng)(嵌入式設(shè)備蹭睡、小型設(shè)備)
?避開了寄存器的分配難題衍菱;使用零地址指令(沒有地址,只有操作數(shù))方式分配
?指令流中的指令大部分是零地址指令肩豁,其執(zhí)行流程依賴于操作棧(只需要操作棧頂)脊串。指令集更小(字節(jié)碼文件中每8位字節(jié)進(jìn)行對(duì)齊),編譯器容易實(shí)現(xiàn)
?不需要硬件支持清钥,可移植性更好琼锋,更好實(shí)現(xiàn)跨平臺(tái)(因?yàn)闂J莾?nèi)存層面的)
?缺點(diǎn)是性能下降,實(shí)現(xiàn)同樣的功能需要更多的指令
JVM的生命周期
虛擬機(jī)的啟動(dòng)
Java虛擬機(jī)的啟動(dòng)時(shí)通過引導(dǎo)類加載器(bootstrap class loader)創(chuàng)建一個(gè)初始類(initial class)來完成的祟昭,這個(gè)類由虛擬機(jī)的具體實(shí)現(xiàn)指定的缕坎。
虛擬機(jī)的執(zhí)行
?一個(gè)運(yùn)行中的Java虛擬機(jī)的任務(wù)是執(zhí)行Java程序
?程序開始執(zhí)行時(shí)他才運(yùn)行,程序結(jié)束他就停止
?執(zhí)行一個(gè)所謂的Java程序的時(shí)候从橘,真真正正在執(zhí)行的是一個(gè)叫做Java虛擬機(jī)的進(jìn)程
虛擬機(jī)的退出
?程序正常執(zhí)行結(jié)束
?程序在執(zhí)行過程中遇到了異衬罡希或錯(cuò)誤而異常終止
?由于操作系統(tǒng)出現(xiàn)錯(cuò)誤從而導(dǎo)致Java虛擬機(jī)進(jìn)程終止
?某線程調(diào)用調(diào)用Runtime類或System類的exit方法础钠,或Runtime類的halt方法,并且Java安全管理器也允許這次exit或halt操作(主動(dòng)結(jié)束程序執(zhí)行)
?Java本地方法接口(JNI-Java Native Interface)規(guī)范中描述的用JNI Invocation API來加載或卸載Java虛擬機(jī)時(shí)叉谜,Java虛擬機(jī)的退出情況