溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何深入了解JVM內(nèi)存結(jié)構(gòu)

發(fā)布時(shí)間:2021-10-23 17:03:30 來(lái)源:億速云 閱讀:125 作者:柒染 欄目:編程語(yǔ)言

如何深入了解JVM內(nèi)存結(jié)構(gòu),很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

你對(duì)JVM內(nèi)存結(jié)構(gòu)是否熟悉,這里向大家描述一下,主要包括類裝載子系統(tǒng),方法區(qū),PC寄存器,堆和棧等內(nèi)容,其中方法區(qū)被所有線程共享,垃圾收集也會(huì)清理方法區(qū)中的無(wú)用類型對(duì)象。

JVM內(nèi)存結(jié)構(gòu)

1)JVM內(nèi)存結(jié)構(gòu)之類裝載子系統(tǒng)

裝載連接初始化

(2)JVM內(nèi)存結(jié)構(gòu)之方法區(qū)。

被所有線程共享。垃圾收集也會(huì)清理方法區(qū)中的無(wú)用類型對(duì)象。

a.類型信息。 

  類加載器加載類時(shí),從類文件中提取出來(lái)。

類的完整有效名

父類的完整有效名(interfaceandjava.lang.Object除外,因?yàn)闊o(wú)父類)

類型的修飾符

類型直接接口列表

b.常量池。

存儲(chǔ)了一個(gè)類型所使用的常量所有類型、域和方法的符號(hào)引用。

c.域信息。

jvm必須在方法區(qū)中保存類型的所有域的相關(guān)信息以及域的聲明順序,

域的相關(guān)信息包括:

域名

域類型

域修飾符(publicprivateprotectedstaticfinalvolatiletransient…)

d.方法信息。

方法名

方法返回類型

方法參數(shù)

方法的修飾符

方法的字節(jié)碼(abstractandnative除外)(被PC寄存器指向)

操作數(shù)棧和方法棧幀的局部變量區(qū)的大小

異常表

e.類的靜態(tài)變量(所有對(duì)象共享一分拷貝)

f.類的被聲明為final的類變量(所有對(duì)象共享一分拷貝)

g.加載一個(gè)類的類加載器的引用

h.Class類的引用

i.方法表。

j.一個(gè)例子:

ClassLava{  privateintspeed=5;  voidflow();  }   ClassVolcano{  publicstaticvoidmain(String[]args){  Lavalava=newLava();  lava.flow();  }  }

下面我們描述一下main()方法的***條指令的字節(jié)碼是如何被執(zhí)行的。不同的jvm實(shí)現(xiàn)的差別很大,這里只是其中之一。

為了運(yùn)行這個(gè)程序,你以某種方式把“Volcano"傳給了jvm。有了這個(gè)名字,jvm找到了這個(gè)類文件(Volcano.class)并讀入,它從類文件提取了類型信息并放在了方法區(qū)中,通過(guò)解析存在方法區(qū)中的字節(jié)碼,jvm激活了main()方法,在執(zhí)行時(shí),jvm保持了一個(gè)指向當(dāng)前類(Volcano)常量池的指針。

注意jvm在還沒(méi)有加載Lava類的時(shí)候就已經(jīng)開(kāi)始執(zhí)行了。正像大多數(shù)的jvm一樣,不會(huì)等所有類都加載了以后才開(kāi)始執(zhí)行,它只會(huì)在需要的時(shí)候才加載。

main()的***條指令告知jvm為列在常量池***項(xiàng)的類分配足夠的內(nèi)存。

jvm使用指向Volcano常量池的指針找到***項(xiàng),發(fā)現(xiàn)是一個(gè)對(duì)Lava類的符號(hào)引用,然后它就檢查方法區(qū)看lava是否已經(jīng)被加載了。

這個(gè)符號(hào)引用僅僅是類lava的完整有效名”lava“。這里我們看到為了jvm能盡快從一個(gè)名稱找到一個(gè)類,一個(gè)良好的數(shù)據(jù)結(jié)構(gòu)是多么重要。這里jvm的實(shí)現(xiàn)者可以采用各種方法,如hash表,查找樹(shù)等等。同樣的算法可以用于Class類的forName()的實(shí)現(xiàn)。

當(dāng)jvm發(fā)現(xiàn)還沒(méi)有加載過(guò)一個(gè)稱為"Lava"的類,它就開(kāi)始查找并加載類文件"Lava.class"。它從類文件中抽取類型信息并放在了方法區(qū)中。

jvm于是以一個(gè)直接指向方法區(qū)lava類的指針替換了常量池***項(xiàng)的符號(hào)引用。以后就可以用這個(gè)指針快速的找到lava類了。而這個(gè)替換過(guò)程稱為常量池解析(constantpoolresolution)。在這里我們替換的是一個(gè)native指針。

jvm終于開(kāi)始為新的lava對(duì)象分配空間了。這次,jvm仍然需要方法區(qū)中的信息。它使用指向lava數(shù)據(jù)的指針(剛才指向volcano常量池***項(xiàng)的指針)找到一個(gè)lava對(duì)象究竟需要多少空間。

一旦jvm知道了一個(gè)Lava對(duì)象所要的空間,它就在堆上分配這個(gè)空間并把這個(gè)實(shí)例的變量speed初始化為缺省值0。假如lava的父對(duì)象也有實(shí)例變量,則也會(huì)初始化。

當(dāng)把新生成的lava對(duì)象的引用壓到棧中,***條指令也結(jié)束了。下面的指令利用這個(gè)引用激活java代碼把speed變量設(shè)為初始值,5。另外一條指令會(huì)用這個(gè)引用激活Lava對(duì)象的flow()方法。

(3)JVM內(nèi)存結(jié)構(gòu)之堆。

存放運(yùn)行時(shí)所有對(duì)象和數(shù)組。

(4)JVM內(nèi)存結(jié)構(gòu)之棧。

每次啟動(dòng)一個(gè)新的線程,就會(huì)被分配一個(gè)棧。

(5)JVM內(nèi)存結(jié)構(gòu)之PC寄存器(程序計(jì)數(shù)器)

總是指向該線程下一步要執(zhí)行的指令。指令的位置放在方法區(qū)的方法字節(jié)碼中。內(nèi)容是相對(duì)于指令的偏移量。


看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

jvm
AI