小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

深入淺出:圖形化淺析JAVA程序運(yùn)行模式及虛擬機(jī)JVM

 諤諤熱 2017-09-03

本文主要對Java程序的執(zhí)行模式和JVM的架構(gòu)原理進(jìn)行較易理解的介紹和剖析,以便能更好的掌握J(rèn)ava的核心機(jī)制和基本原理,拋磚引玉,以便引起Java愛好這的興趣。如果覺得有用,請點(diǎn)個(gè)贊,順手分享本文。Thanks a lot.

一、Java程序的兩個(gè)環(huán)境

所謂Java程序,即用Java語言編寫的程序,它包含數(shù)據(jù)、代碼以及相關(guān)算法。而一個(gè)有效的java程序,滿足兩個(gè)環(huán)境的要求,即編譯環(huán)境和運(yùn)行環(huán)境。如下圖所示:

深入淺出:圖形化淺析JAVA程序運(yùn)行模式及虛擬機(jī)JVM

圖-1:Java程序運(yùn)行環(huán)

根據(jù)上圖所示:

其一,在編譯環(huán)境中,我們基于Java語言和JDK(Java開發(fā)工具包),進(jìn)行源程序的代碼編寫,并在確保正確的情況下,通過工具包提供編譯器,把所有源代碼(即.java)編譯成(通過javac命令實(shí)現(xiàn))字節(jié)碼文件(即.class文件)。

其二,在運(yùn)行時(shí)環(huán)境執(zhí)行程序,或說運(yùn)行程序。這時(shí),需要先擁有待運(yùn)行程序的字節(jié)碼文件。這些字節(jié)碼文件有可能通過網(wǎng)絡(luò)或者在本地兩種方式傳遞到運(yùn)行時(shí)環(huán)境。

運(yùn)行時(shí)環(huán)境中主要的工作就是啟動(dòng)Java虛擬機(jī),并通過虛擬機(jī)來完成一系列工作,實(shí)現(xiàn)java程序的運(yùn)行。需要注意的是,在java虛擬執(zhí)行程序時(shí),它會根據(jù)需要來加載Java提供的相關(guān)API的class文件。

二、Java的JVM運(yùn)行結(jié)構(gòu)

基于上面的java程序運(yùn)行的框架圖,我們進(jìn)一步來透視java的核心基石,即java虛擬機(jī)JVM的內(nèi)部運(yùn)行組成。

根據(jù)Java的虛擬機(jī)規(guī)范,JVM內(nèi)部抽象體系結(jié)構(gòu)主要有這樣幾大部分組成,即類裝載器子系統(tǒng)、執(zhí)行引擎以及運(yùn)行時(shí)數(shù)據(jù)管理區(qū),同時(shí)要求支持本地方法的調(diào)用機(jī)制。那么這樣一來,我們進(jìn)一步細(xì)化Java程序的JVM內(nèi)部執(zhí)行機(jī)制,就形成如下的Java運(yùn)行模式架構(gòu):

深入淺出:圖形化淺析JAVA程序運(yùn)行模式及虛擬機(jī)JVM

圖-2:JVM運(yùn)行流程結(jié)構(gòu)圖

三、JVM的架構(gòu)原理和運(yùn)行機(jī)制

經(jīng)過上一部分的內(nèi)容的抽象和總結(jié),那么我們可以進(jìn)一步抽象出基于java虛擬機(jī)規(guī)范實(shí)現(xiàn)的一般的JVM實(shí)現(xiàn)組成架構(gòu)以及其運(yùn)行機(jī)制和原理。JVM詳細(xì)的參考架構(gòu)圖如下:

深入淺出:圖形化淺析JAVA程序運(yùn)行模式及虛擬機(jī)JVM

圖-3:虛擬機(jī)JVM參考實(shí)現(xiàn)圖

針對上圖JVM參考架構(gòu),作簡要說明如下:

虛擬機(jī)JVM主要有三個(gè)子系統(tǒng)構(gòu)成:

1-類裝入器子系統(tǒng)

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

3-執(zhí)行引擎

1.類裝入器子系統(tǒng)

Java的動(dòng)態(tài)類加載功能是由類裝入器子系統(tǒng)。 由他進(jìn)行類的裝載、鏈接、并初始化類文件時(shí),是指一個(gè)類第一次運(yùn)行時(shí),而不是編譯時(shí)間。

1.1類加載

深入淺出:圖形化淺析JAVA程序運(yùn)行模式及虛擬機(jī)JVM

1)Bootstrap類加載器

負(fù)責(zé)加載$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++實(shí)現(xiàn),不是ClassLoader子類

2)Extension類加載器

負(fù)責(zé)加載java平臺中擴(kuò)展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目錄下的jar包

3)Application類加載器

負(fù)責(zé)記載classpath中指定的jar包及目錄中class

4)Custom類加載器

屬于應(yīng)用程序根據(jù)自身需要自定義的ClassLoader,如tomcat、jboss都會根據(jù)j2ee規(guī)范自行實(shí)現(xiàn)ClassLoader。加載過程中會先檢查類是否被已加載,檢查順序是自底向上,從Custom ClassLoader到BootStrap ClassLoader逐層檢查,只要某個(gè)classloader已加載就視為已加載此類,保證此類只所有ClassLoader加載一次。而加載的順序是自頂向下,也就是由上層來逐層嘗試加載此類。

1.2連接

驗(yàn)證——字節(jié)碼校驗(yàn)器會檢查生成的字節(jié)碼是否正確,如果驗(yàn)證失敗則會驗(yàn)證錯(cuò)誤。

準(zhǔn)備——對于所有靜態(tài)變量的內(nèi)存分配和默認(rèn)值分配。

識別——解析或識別是從運(yùn)行時(shí)常量池的符號引用中動(dòng)態(tài)具體值的過程。

1.3初始化

這是類裝入的最后階段, 類或接口的初始化由執(zhí)行類或接口初始化方法構(gòu)成。這里所有的靜態(tài)變量與原來的值將被指派,靜態(tài)塊將被執(zhí)行。

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

運(yùn)行時(shí)數(shù)據(jù)區(qū)域分為5個(gè)主要組件:

深入淺出:圖形化淺析JAVA程序運(yùn)行模式及虛擬機(jī)JVM

方法區(qū)——所有的類級別的數(shù)據(jù)將存儲在這里,包括靜態(tài)變量。 每個(gè)JVM區(qū)域只有一個(gè)方法,它是一個(gè)共享資源。一般會包含一個(gè)運(yùn)行時(shí)常量池(運(yùn)行時(shí)常量池:一個(gè)存儲了類文件格式中的常量池表的內(nèi)存空間。這部分空間雖然存在于方法區(qū)內(nèi),但卻在JVM操作中扮演著舉足輕重的角色,因此JVM規(guī)范單獨(dú)把這一部分拿出來描述。除了每個(gè)類或接口中定義的常量,它還包含了所有對方法和字段的引用。因此當(dāng)需要一個(gè)方法或字段時(shí),JVM通過運(yùn)行時(shí)常量池中的信息從內(nèi)存空間中來查找其相應(yīng)的實(shí)際地址)。

堆區(qū)域——所有的對象和相應(yīng)的實(shí)例變量和數(shù)組將存儲在這里。 還有一堆區(qū)域每個(gè)JVM。 自方法和堆區(qū)域多個(gè)線程共享內(nèi)存,存儲的數(shù)據(jù)不是線程安全的。

棧區(qū)域——每一個(gè)線程創(chuàng)建一個(gè)單獨(dú)的運(yùn)行時(shí)堆棧。 對于每一個(gè)方法調(diào)用,一個(gè)稱為棧內(nèi)存棧幀被創(chuàng)建。 所有局部變量將被創(chuàng)建在棧內(nèi)存中。 棧區(qū)域是線程安全的,因?yàn)樗皇且粋€(gè)共享資源。 棧幀分三個(gè)實(shí)體:

其一,局部變量數(shù)組——有多少相關(guān)的方法局部變量以及相應(yīng)的值將被存儲在這里。

其二,操作數(shù)?!绻魏沃虚g操作要求執(zhí)行,操作數(shù)棧作為運(yùn)行時(shí)工作區(qū)執(zhí)行操作。

其三,幀數(shù)據(jù)——所有的符號對應(yīng)的方法存儲在這里。 在任何的情況下異常catch塊信息將保存在幀數(shù)據(jù)。

程序計(jì)數(shù)器——每個(gè)線程必須分開程序計(jì)數(shù)器登記,當(dāng)前執(zhí)行的指令一旦執(zhí)行,程序計(jì)數(shù)器(程序計(jì)數(shù)登記器)更新下一個(gè)指令。

本地方法棧——本地方法棧保存本機(jī)方法的信息。 為每一個(gè)線程將創(chuàng)建一個(gè)單獨(dú)的本地方法棧,以備不時(shí)之用。

3.執(zhí)行引擎

通過類裝載器裝載的,被分配到JVM的運(yùn)行時(shí)數(shù)據(jù)區(qū)的字節(jié)碼會被執(zhí)行引擎執(zhí)行。執(zhí)行引擎以指令為單位讀取Java字節(jié)碼。它就像一個(gè)CPU一樣,一條一條地執(zhí)行機(jī)器指令。每個(gè)字節(jié)碼指令都由一個(gè)1字節(jié)的操作碼和附加的操作數(shù)組成。執(zhí)行引擎取得一個(gè)操作碼,然后根據(jù)操作數(shù)來執(zhí)行任務(wù),完成后就繼續(xù)執(zhí)行下一條操作碼。如下圖所示:

深入淺出:圖形化淺析JAVA程序運(yùn)行模式及虛擬機(jī)JVM

不過Java字節(jié)碼是用一種人類可以讀懂的語言編寫的,而不是用機(jī)器可以直接執(zhí)行的語言。因此,執(zhí)行引擎必須把字節(jié)碼轉(zhuǎn)換成可以直接被JVM執(zhí)行的語言。字節(jié)碼可以通過以下兩種方式轉(zhuǎn)換成合適的語言。執(zhí)行引擎主要包括3部分內(nèi)容:

(1)解釋器:一條一條地讀取,解釋并且執(zhí)行字節(jié)碼指令。因?yàn)樗粭l一條地解釋和執(zhí)行指令,所以它可以很快地解釋字節(jié)碼,但是執(zhí)行起來會比較慢。這是解釋執(zhí)行的語言的一個(gè)缺點(diǎn)。字節(jié)碼這種“語言”基本來說是解釋執(zhí)行的。

(2)即時(shí)(Just-In-Time)編譯器:即時(shí)編譯器被引入用來彌補(bǔ)解釋器的缺點(diǎn)。執(zhí)行引擎首先按照解釋執(zhí)行的方式來執(zhí)行,然后在合適的時(shí)候,即時(shí)編譯器把整段字節(jié)碼編譯成本地代碼。然后,執(zhí)行引擎就沒有必要再去解釋執(zhí)行方法了,它可以直接通過本地代碼去執(zhí)行它。執(zhí)行本地代碼比一條一條進(jìn)行解釋執(zhí)行的速度快很多。編譯后的代碼可以執(zhí)行的很快,因?yàn)楸镜卮a是保存在緩存里的。

不過,用JIT編譯器來編譯代碼所花的時(shí)間要比用解釋器去一條條解釋執(zhí)行花的時(shí)間要多。因此,如果代碼只被執(zhí)行一次的話,那么最好還是解釋執(zhí)行而不是編譯后再執(zhí)行。因此,內(nèi)置了JIT編譯器的JVM都會檢查方法的執(zhí)行頻率,如果一個(gè)方法的執(zhí)行頻率超過一個(gè)特定的值的話,那么這個(gè)方法就會被編譯成本地代碼。JIT中不要構(gòu)成如下:

2中間代碼生成器(Intermediate Code Generator):生成中間代碼

2代碼優(yōu)化器(Code Optimizer):負(fù)責(zé)優(yōu)化上面生成的中間代碼

2目標(biāo)代碼生成器(Target Code Generator):負(fù)責(zé)生成機(jī)器代碼或本地代碼

2分析器(Profiler):一個(gè)特殊組件,負(fù)責(zé)查找熱點(diǎn),即該方法是否被多次調(diào)用;

可以簡單這樣理解,JIT編譯器通過中間代碼生成器生成中間代碼,再通過代碼優(yōu)化器負(fù)責(zé)優(yōu)化生成中間代碼,最后由目標(biāo)代碼生成器負(fù)責(zé)生成機(jī)器代碼或本機(jī)代碼。在這過程中,JIT的分析器,一個(gè)特殊的組件,負(fù)責(zé)尋找熱點(diǎn),即是否多次調(diào)用的方法,再執(zhí)行上述操作。

(3)垃圾收集器(Garbage Collector):收集和刪除未引用的對象??梢酝ㄟ^調(diào)用System.gc()觸發(fā)垃圾收集,但不能保證執(zhí)行。JVM的垃圾回收對象是已創(chuàng)建的對象。

另外,Java Native Interface(JNI): JNI將與本機(jī)方法庫進(jìn)行交互,并提供執(zhí)行引擎所需的本機(jī)庫。本地方法庫(Native Method Libraries)是執(zhí)行引擎所需的本機(jī)庫的集合。

(文末)——謝謝閱讀,希望對你有所幫助。別忘了,點(diǎn)個(gè)贊、分享本文,并關(guān)注本頭條號喲~


    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多