java運(yùn)行原理

了解Java的工作原理以幫助自己深入理解java


1.java程序運(yùn)行圖示:

java程序運(yùn)行圖示

跨平臺(tái)說(shuō)明:java編譯器 (編譯) → 虛擬機(jī)(解釋執(zhí)行) → 解釋器(翻譯) → 機(jī)器碼這里來(lái)說(shuō)明一下,java經(jīng)編譯生成字節(jié)碼.class,這是JVM能夠理解的語(yǔ)言,JVM 進(jìn)行解釋和執(zhí)行,然后通過(guò)其上的解釋器對(duì)JVM所做的結(jié)果進(jìn)行翻譯,翻譯成各自所在平臺(tái)上的機(jī)器碼。

2.JVM實(shí)現(xiàn)類(lèi)的加載圖示

2.1

類(lèi)的層級(jí)結(jié)構(gòu)圖示

--Bootstrap class loader: 當(dāng)運(yùn)行java虛擬機(jī)時(shí),這個(gè)類(lèi)加載器被創(chuàng)建,它加載一些基本的Java API,包括Object這個(gè)類(lèi)。需要注意的是,這個(gè)類(lèi)加載器不是用java語(yǔ)言寫(xiě)的,而是用C/C++寫(xiě)的。

--Extension class loader: 這個(gè)加載器加載出了基本API之外的一些拓展類(lèi),包括一些與安全性能相關(guān)的類(lèi)。

--System Class Loader: 它加載應(yīng)用程序中的類(lèi),也就是在你的classpath中配置的類(lèi)。

--User-Defined Class Loader: 這是開(kāi)發(fā)人員通過(guò)拓展ClassLoader類(lèi)定義的自定義加載器,加載程序員定義的一些類(lèi)。

2.2


委派模式圖示

定義的類(lèi)在加載之前,虛擬機(jī)會(huì)先做檢查,即所在的命名空間中是否已經(jīng)存在該類(lèi),這種檢查方式是自下而上的。在檢查報(bào)告未發(fā)現(xiàn)該類(lèi)時(shí),最底層(對(duì)應(yīng)圖示最頂層)會(huì)嘗試加載,若未找到該類(lèi),就委派給上層加載,該加載過(guò)程是自上而下的。


3.加載類(lèi)后的執(zhí)行過(guò)程


裝載后JVM執(zhí)行過(guò)程

當(dāng)存在類(lèi)加載器對(duì)類(lèi)進(jìn)行裝載后,然后讀取這個(gè)CLASS文件(一個(gè)線(xiàn)性二進(jìn)制數(shù)據(jù)流),將它傳入java虛擬機(jī)中。緊接著虛擬機(jī)提取其中的類(lèi)型信息。比如:該類(lèi)的類(lèi)名,方法名,變量名,修飾符,方法的返回類(lèi)型等等。還有一個(gè)重要的東西就是常量池。(常量池保存了該類(lèi)型的所有常量,包括直接常量和對(duì)其他類(lèi)型,字段,方法的符號(hào)引用)將這些信息保存在一個(gè)叫做方法區(qū)的地方。最終形成CLASS類(lèi)的實(shí)例,這個(gè)實(shí)例存放在內(nèi)存的堆區(qū)。它成為了java程序與內(nèi)部數(shù)據(jù)結(jié)構(gòu)之間的接口,程序要訪問(wèn)該類(lèi)型的信息,程序就調(diào)用該類(lèi)型對(duì)應(yīng)的CLASS實(shí)例對(duì)象的方法。簡(jiǎn)而言之:這個(gè)過(guò)程就是把一個(gè)類(lèi)型的二進(jìn)制數(shù)據(jù)解析為方法區(qū)中的內(nèi)部數(shù)據(jù)結(jié)構(gòu),并在堆上建立一個(gè)CLASS對(duì)象的過(guò)程。

對(duì)各步做出簡(jiǎn)要說(shuō)明:

Verifying:檢查載入的類(lèi)文件是否符合Java規(guī)范和虛擬機(jī)規(guī)范,例如重寫(xiě)的函數(shù)名稱(chēng),參數(shù)相同而返回值類(lèi)型不同。

Preparing:為這個(gè)類(lèi)分配所需要的內(nèi)存,確定這個(gè)類(lèi)的屬性、方法等所需的數(shù)據(jù)結(jié)構(gòu)。(Prepare a data structure that assigns the memory required by classes and indicates the fields, methods, and interfaces defined in the class.)

Resolving:在類(lèi)型的常量池中尋找類(lèi),接口,字段和方法的符合引用把這些符號(hào)引用替換成直接引用的過(guò)程

Initialing:初始化類(lèi)的局部變量,為靜態(tài)域賦值,同時(shí)執(zhí)行靜態(tài)初始化塊。


4.加載后運(yùn)行細(xì)節(jié)


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

當(dāng)運(yùn)行一個(gè)JVM示例時(shí),系統(tǒng)將分配給它一塊內(nèi)存區(qū)域(這塊內(nèi)存區(qū)域的大小可以設(shè)置的),這一內(nèi)存區(qū)域由JVM自己來(lái)管理。從這一塊內(nèi)存中分出一塊用來(lái)存儲(chǔ)一些運(yùn)行數(shù)據(jù),例如創(chuàng)建的對(duì)象,傳遞給方法的參數(shù),局部變量,返回值等等。分出來(lái)的這一塊就稱(chēng)為運(yùn)行數(shù)據(jù)區(qū)域。運(yùn)行數(shù)據(jù)區(qū)域可以劃分為6大塊:Java棧、程序計(jì)數(shù)寄存器(PC寄存器)、本地方法棧(Native Method Stack)、Java堆、方法區(qū)域、運(yùn)行常量池(Runtime Constant Pool)。運(yùn)行常量池本應(yīng)該屬于方法區(qū),但是由于其重要性,JVM規(guī)范將其獨(dú)立出來(lái)說(shuō)明。其中,前面3各區(qū)域(PC寄存器、Java棧、本地方法棧)是每個(gè)線(xiàn)程獨(dú)自擁有的,后三者則是整個(gè)JVM實(shí)例中的所有線(xiàn)程共有的。

對(duì)各區(qū)的簡(jiǎn)易說(shuō)明:

PC計(jì)數(shù)器: 每一個(gè)線(xiàn)程都擁有一個(gè)PC計(jì)數(shù)器,當(dāng)線(xiàn)程啟動(dòng)(start)時(shí),PC計(jì)數(shù)器被創(chuàng)建,這個(gè)計(jì)數(shù)器存放當(dāng)前正在被執(zhí)行的字節(jié)碼指令(JVM指令)的地址。

Java棧: 同樣的,Java棧也是每個(gè)線(xiàn)程單獨(dú)擁有,線(xiàn)程啟動(dòng)時(shí)創(chuàng)建。這個(gè)棧中存放著一系列的棧幀(Stack Frame),JVM只能進(jìn)行壓入(Push)和彈出(Pop)棧幀這兩種操作。每當(dāng)調(diào)用一個(gè)方法時(shí),JVM就往棧里壓入一個(gè)棧幀,方法結(jié)束返回時(shí)彈出棧幀。如果方法執(zhí)行時(shí)出現(xiàn)異常,可以調(diào)用printStackTrace等方法來(lái)查看棧的情況。

本地方法棧 :當(dāng)程序通過(guò)JNI(Java Native Interface)調(diào)用本地方法(如C或者C++代碼)時(shí),就根據(jù)本地方法的語(yǔ)言類(lèi)型建立相應(yīng)的棧。

方法區(qū)域 :方法區(qū)域是一個(gè)JVM實(shí)例中的所有線(xiàn)程共享的,當(dāng)啟動(dòng)一個(gè)JVM實(shí)例時(shí),方法區(qū)域被創(chuàng)建。它用于存運(yùn)行放常量池、有關(guān)域和方法的信息、靜態(tài)變量、類(lèi)和方法的字節(jié)碼。不同的JVM實(shí)現(xiàn)方式在實(shí)現(xiàn)方法區(qū)域的時(shí)候會(huì)有所區(qū)別。Oracle的HotSpot稱(chēng)之為永久區(qū)域(Permanent Area)或者永久代(Permanent Generation)。

運(yùn)行常量池: 這個(gè)區(qū)域存放類(lèi)和接口的常量,除此之外,它還存放方法和域的所有引用。當(dāng)一個(gè)方法或者域被引用的時(shí)候,JVM就通過(guò)運(yùn)行常量池中的這些引用來(lái)查找方法和域在內(nèi)存中的的實(shí)際地址。

堆(Heap): 堆中存放的是程序創(chuàng)建的對(duì)象或者實(shí)例。這個(gè)區(qū)域?qū)VM的性能影響很大。垃圾回收機(jī)制處理的正是這一塊內(nèi)存區(qū)域。(Java虛擬機(jī)內(nèi)部會(huì)根據(jù)一種規(guī)則(這個(gè)對(duì)象是否可以觸及)來(lái)判斷這兩個(gè)類(lèi)是否可以回收了?當(dāng)執(zhí)行類(lèi)= null;時(shí)這條線(xiàn)就被斬?cái)嗔?,因此?lèi)實(shí)例就不可以觸及了,java虛擬機(jī)就可以回收這個(gè)類(lèi)實(shí)例了)


?聲明:這里感謝lovebeautyLust-Ring兩位博主,我只是當(dāng)了搬運(yùn)工,理理思路幫助成長(zhǎng),絕無(wú)冒犯!

最后編輯于
?著作權(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)容

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