JVM学习--(一)基本原理
前言
? JVM一直是java知識(shí)里面進(jìn)階階段的重要部分,如果希望在java領(lǐng)域研究的更深入,則JVM則是如論如何也避開(kāi)不了的話(huà)題,本系列試圖通過(guò)簡(jiǎn)潔易讀的方式,講解JVM必要的知識(shí)點(diǎn)。
運(yùn)行流程
? 我們都知道java一直宣傳的口號(hào)是:一次編譯,到處運(yùn)行。那么它如何實(shí)現(xiàn)的呢?我們看下圖:
? java程序經(jīng)過(guò)一次編譯之后,將java代碼編譯為字節(jié)碼也就是class文件,然后在不同的操作系統(tǒng)上依靠不同的java虛擬機(jī)進(jìn)行解釋,最后再轉(zhuǎn)換為不同平臺(tái)的機(jī)器碼,最終得到執(zhí)行。這樣我們是不是可以推演,如果要在mac系統(tǒng)上運(yùn)行,是不是只需要安裝mac java虛擬機(jī)就行了。那么了解了這個(gè)基本原理后,我們嘗試去做更深的研究,一個(gè)普通的java程序它的執(zhí)行流程到底是怎樣的呢?例如我們寫(xiě)了一段這樣的代碼:
public class HelloWorld { public static void main(String[] args) { System.out.print("Hello world"); } }
這段程序從編譯到運(yùn)行,最終打印出“Hello world”中間經(jīng)過(guò)了哪些步驟呢?我們直接上圖:
? java代碼通過(guò)編譯之后生成字節(jié)碼文件(class文件),通過(guò):java HelloWorld執(zhí)行,此時(shí)java根據(jù)系統(tǒng)版本找到j(luò)vm.cfg,各位可以搜索一下自己電腦上的jvm.cfg文件在哪,它會(huì)根據(jù)你的系統(tǒng)版本放在不同的位置,比如我的這個(gè)文件就在:C:\Program Files\Java\jdk1.8.0_101\jre\lib\amd64\jvm.cfg,打開(kāi)看一下:
? 這是我電腦上的文件,其中-server KNOWN就表示名稱(chēng)為server的jvm可用。如果這時(shí)你搜索一下你電腦上jvm.dll,你就會(huì)發(fā)現(xiàn)它一定在你的某個(gè)server目錄下,比如我的:C:\Program Files\Java\jdk1.8.0_101\jre\bin\server\jvm.dll。簡(jiǎn)而言之就是通過(guò)jvm.cfg文件找到對(duì)應(yīng)的jvm.dll,jvm.dll則是java虛擬機(jī)的主要實(shí)現(xiàn)。接下來(lái)會(huì)初始化JVM,并且獲取JNI接口,什么是JNI接口,就是java本地接口,你想啊java被編譯成了class文件,JVM怎么從硬盤(pán)上找到這個(gè)文件并裝載到JVM里呢,就是通過(guò)JNI接口(它還常用于java與操作系統(tǒng)、硬件交互),找到class文件后并裝載進(jìn)JVM,然后找到main方法,最后執(zhí)行。
JVM基本結(jié)構(gòu)
? 可能通過(guò)上面的描述,大家對(duì)JVM運(yùn)行流程有了一個(gè)粗略的認(rèn)識(shí),那么JVM內(nèi)部到底是怎么執(zhí)行一個(gè)class文件的呢,也就是上圖中最后一步第6步的內(nèi)部細(xì)節(jié)是怎樣的呢?要了解這個(gè)問(wèn)題,我們首先得看一下JVM的內(nèi)部結(jié)構(gòu):
? 從這個(gè)結(jié)構(gòu)不難看出,class文件被jvm裝載以后,經(jīng)過(guò)jvm的內(nèi)存空間調(diào)配,最終是由執(zhí)行引擎完成class文件的執(zhí)行。當(dāng)然這個(gè)過(guò)程還有其他角色模塊的協(xié)助,這些模塊協(xié)同配合才能讓一個(gè)java程序成功的運(yùn)行,下面就詳細(xì)介紹這些模板,它們也是后面學(xué)習(xí)jvm最重要的部分。
內(nèi)存空間:
JVM內(nèi)存空間包含:方法區(qū)、java堆、java棧、本地方法棧。
方法區(qū)是各個(gè)線(xiàn)程共享的區(qū)域,存放類(lèi)信息、常量、靜態(tài)變量。
java堆也是線(xiàn)程共享的區(qū)域,我們的類(lèi)的實(shí)例就放在這個(gè)區(qū)域,可以想象你的一個(gè)系統(tǒng)會(huì)產(chǎn)生很多實(shí)例,因此java堆的空間也是最大的。如果java堆空間不足了,程序會(huì)拋出OutOfMemoryError異常。
java棧是每個(gè)線(xiàn)程私有的區(qū)域,它的生命周期與線(xiàn)程相同,一個(gè)線(xiàn)程對(duì)應(yīng)一個(gè)java棧,每執(zhí)行一個(gè)方法就會(huì)往棧中壓入一個(gè)元素,這個(gè)元素叫“棧幀”,而棧幀中包括了方法中的局部變量、用于存放中間狀態(tài)值的操作棧,這里面有很多細(xì)節(jié),我們以后再講。如果java棧空間不足了,程序會(huì)拋出StackOverflowError異常,想一想什么情況下會(huì)容易產(chǎn)生這個(gè)錯(cuò)誤,對(duì),遞歸,遞歸如果深度很深,就會(huì)執(zhí)行大量的方法,方法越多java棧的占用空間越大。
本地方法棧角色和java棧類(lèi)似,只不過(guò)它是用來(lái)表示執(zhí)行本地方法的,本地方法棧存放的方法調(diào)用本地方法接口,最終調(diào)用本地方法庫(kù),實(shí)現(xiàn)與操作系統(tǒng)、硬件交互的目的。
PC寄存器,說(shuō)到這里我們的類(lèi)已經(jīng)加載了,實(shí)例對(duì)象、方法、靜態(tài)變量都去了自己改去的地方,那么問(wèn)題來(lái)了,程序該怎么執(zhí)行,哪個(gè)方法先執(zhí)行,哪個(gè)方法后執(zhí)行,這些指令執(zhí)行的順序就是PC寄存器在管,它的作用就是控制程序指令的執(zhí)行順序。
執(zhí)行引擎當(dāng)然就是根據(jù)PC寄存器調(diào)配的指令順序,依次執(zhí)行程序指令。
結(jié)語(yǔ)
? 本文主要介紹了java虛擬機(jī)運(yùn)行的基本流程,以及java虛擬機(jī)內(nèi)部結(jié)構(gòu)。下一篇我們將學(xué)習(xí)java內(nèi)存模型以及探索java變量的可見(jiàn)性、有序性、指令重排等問(wèn)題。
轉(zhuǎn)載于:https://www.cnblogs.com/eer123/p/8542033.html
總結(jié)
以上是生活随笔為你收集整理的JVM学习--(一)基本原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 原神雷电将军几命能用?
- 下一篇: 四千瓦的电锅炉民用可以吗?
