這篇文章主要介紹JVM體系結(jié)構(gòu)是怎么樣的,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
嵊州網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)從2013年開(kāi)始到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)。
先上一張JVM體系結(jié)構(gòu)圖:
1)運(yùn)行時(shí)數(shù)據(jù)區(qū):經(jīng)過(guò)編譯生成的字節(jié)碼文件(class文件),由class loader(類加載子系統(tǒng))加載后交給執(zhí)行引擎執(zhí)行。在執(zhí)行引擎執(zhí)行的過(guò)程中產(chǎn)生的數(shù)據(jù)會(huì)存儲(chǔ)在一塊內(nèi)存區(qū)域。這塊內(nèi)存區(qū)域就是運(yùn)行時(shí)區(qū)域
2)程序計(jì)數(shù)器:用于記錄當(dāng)前線程的正在執(zhí)行的字節(jié)碼指令位置。由于虛擬機(jī)的多線程是切換線程并分配cpu執(zhí)行時(shí)間的方式實(shí)現(xiàn)的,不同線程的執(zhí)行位置都需要記錄下來(lái),因此程序計(jì)數(shù)器是線程私有的
3)虛擬機(jī)棧:虛擬機(jī)棧是java方法執(zhí)行的內(nèi)存結(jié)構(gòu),虛擬機(jī)會(huì)在每個(gè)java方法執(zhí)行時(shí)創(chuàng)建一個(gè)“棧楨”,用于存儲(chǔ)局部變量表,操作數(shù)棧,動(dòng)態(tài)鏈接,方法出口等信息。當(dāng)方法執(zhí)行完畢時(shí),該棧楨會(huì)從虛擬機(jī)棧中出棧。其中局部變量表包含基本數(shù)據(jù)類型和對(duì)象引用;
在java虛擬機(jī)規(guī)范中,對(duì)這個(gè)區(qū)域規(guī)定了兩種異常狀態(tài):如果線程請(qǐng)求的棧的深度大于虛擬機(jī)允許的深度,將拋出StackOverFlowError異常(棧溢出),如果虛擬機(jī)??梢詣?dòng)態(tài)擴(kuò)展(現(xiàn)在大部分java虛擬機(jī)都可以動(dòng)態(tài)擴(kuò)展,只不過(guò)java虛擬機(jī)規(guī)范中也允許固定長(zhǎng)度的java虛擬機(jī)棧),如果擴(kuò)展時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存空間,就會(huì)拋出OutOfmMemoryError異常(沒(méi)有足夠的內(nèi)存)
4)本地方法棧:類似java方法的執(zhí)行有虛擬機(jī)棧,本地方法的執(zhí)行則對(duì)應(yīng)有本地方法棧
5)方法區(qū):用于存儲(chǔ)已被虛擬機(jī)加載的類信息,常量,靜態(tài)變量,即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。線程共享(看存儲(chǔ)的數(shù)據(jù)就知道了)
java虛擬機(jī)規(guī)范對(duì)方法區(qū)的限制非常寬松,除了和java堆一樣不需要連續(xù)的內(nèi)存和可以選擇固定大小或者可擴(kuò)展外,還可以選擇不實(shí)現(xiàn)垃圾收集。相對(duì)而言,垃圾收集在這個(gè)區(qū)域是比較少出現(xiàn)的,但并非數(shù)據(jù)進(jìn)入了方法區(qū)就如永久代的名字一樣永久存在了。
這區(qū)域的內(nèi)存回收目標(biāo)重要是針對(duì)常量池的回收和類型的卸載,一般來(lái)說(shuō)這個(gè)內(nèi)存區(qū)域的回收‘成績(jī)’比較難以令人滿意。尤其是類型的卸載條件非??量?,但是這部分的回收確實(shí)是必要的。在sun公司的bug列表中,曾出現(xiàn)過(guò)的若干個(gè)嚴(yán)重的bug就是由于低版本的HotSpot虛擬機(jī)對(duì)此區(qū)域未完成回收導(dǎo)致的內(nèi)存溢出。
6)java堆(java Heap):堆的主要作用是存放程序運(yùn)行過(guò)程中創(chuàng)建的對(duì)象實(shí)例,因?yàn)橐娣诺膶?duì)象實(shí)例有可能會(huì)極多,因此也是虛擬機(jī)內(nèi)存管理中最大的一塊。并且由于硬件條件有限,所以需要不斷回收已“無(wú)用”的實(shí)例對(duì)象來(lái)騰出空間給新生成的實(shí)例對(duì)象;因此java的垃圾回收主要是針對(duì)堆進(jìn)行回收的(還有方法區(qū)的常量池),java堆很多時(shí)候也被稱為GC堆(Garbage Collected Heap)。
7)類加載機(jī)制(Class Loader):類加載子系統(tǒng)是根據(jù)一個(gè)類的全限定名來(lái)加載該類的二進(jìn)制流到內(nèi)存中,在JVM中將形成一份描述Class結(jié)構(gòu)的元信息對(duì)象(方法區(qū)),通過(guò)該元信息對(duì)象可以獲知Class的結(jié)構(gòu)信息:如構(gòu)造函數(shù),屬性和方法等,Java允許用戶借由這個(gè)Class相關(guān)的元信息對(duì)象間接調(diào)用Class對(duì)象的功能。
好!說(shuō)了這么多關(guān)鍵字,再拿例子來(lái)講解一下這些關(guān)鍵字:
A.圖1是我們寫的HelloWorld.java,通過(guò)IDE或命令:javac HelloWorld 編譯生成16進(jìn)制的HelloWorld.class(字節(jié)碼文件,見(jiàn)圖3),想讀懂16進(jìn)制字節(jié)可參考:一文讓你明白java字節(jié)碼 ;但一般IDE會(huì)自動(dòng)轉(zhuǎn)譯成圖2的指令;或者通過(guò)命令:javap -verbose HelloWorld 進(jìn)行轉(zhuǎn)譯。
(圖1)HelloWorld.java
(圖2)HelloWorld.class
(圖3)16進(jìn)制的字節(jié)碼:
B.接著,當(dāng)我們通過(guò)IDE或者命令:java HelloWorld 運(yùn)行這個(gè)class文件時(shí),字節(jié)碼文件(class文件)通過(guò)類加載機(jī)制加載完畢交付給執(zhí)行引擎執(zhí)行;類加載機(jī)制把HelloWrold類的信息、靜態(tài)變量(例子中沒(méi)加)、常量(例子中沒(méi)加,常量會(huì)加載到方法區(qū)的常量池,這和靜態(tài)變量不一樣)等加載到方法區(qū)中,接下來(lái)如果需要?jiǎng)?chuàng)建該類的對(duì)象,需要通過(guò)new后面帶的參數(shù)到方法區(qū)進(jìn)行查找類相關(guān)信息。
C.類加載完后,虛擬機(jī)會(huì)檢查程序的入口,虛擬機(jī)中程序的執(zhí)行入口為main函數(shù),如HelloWorld.class中,,執(zhí)行引擎找到main函數(shù)開(kāi)始執(zhí)行指令,并生成一個(gè)“楨棧”入棧至虛擬機(jī)棧的棧頂;我們可以看到(圖2)在main方法下面的命令:0 new java.lang.StringBuilder [16] 表示創(chuàng)建一個(gè)String對(duì)象,創(chuàng)建的String對(duì)象實(shí)例會(huì)在java堆(Heap)中分配內(nèi)存存儲(chǔ)(Java對(duì)象在JVM中的創(chuàng)建過(guò)程可以看這篇文章:Java對(duì)象是怎么創(chuàng)建的(通過(guò)對(duì)象的創(chuàng)建,了解JVM內(nèi)存結(jié)構(gòu))),并把該指令位置“0”記錄到當(dāng)前線程的程序計(jì)數(shù)器中;3 dup 然后把該對(duì)象的引用壓入虛擬機(jī)棧中,并把該指令位置“3”記錄到當(dāng)前線程的程序計(jì)數(shù)器中;4 ldc
D.執(zhí)行引擎執(zhí)行指令過(guò)程中,按需調(diào)用本地庫(kù)接口以執(zhí)行本地庫(kù)方法,如new指令、輸出屏幕等操作
以上是“JVM體系結(jié)構(gòu)是怎么樣的”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!