深入理解Java Runtime Area Java運(yùn)行時(shí)數(shù)據(jù)區(qū)

  • Java Runtime Area的分類
  • 從線程的角度理解Java Runtime Area
  • 從存儲(chǔ)內(nèi)容理解Java Runtime Area
  • 方法區(qū)中究竟存儲(chǔ)了哪些信息?
  • 基本數(shù)據(jù)類型的成員變量放在jvm的哪塊內(nèi)存區(qū)域里?

Java Runtime Area的分類

Java Runtime Area主要可以分為六部分 :

  • Program Counter (PC) Register 程序計(jì)數(shù)器
  • Java Virtual Machine Stacks Java虛擬機(jī)棧
  • Heap Memory Java堆
  • Method Area 方法區(qū)
  • Run-time Constant Pool 運(yùn)行時(shí)常量池
  • Native Method Stacks 本地方法棧

具體的每個(gè)區(qū)域的內(nèi)容和特點(diǎn)可以參考《深入理解Java虛擬機(jī)》,此書已經(jīng)講的很詳細(xì)了。
下面我們對(duì)這幾個(gè)數(shù)據(jù)區(qū)域進(jìn)行分類,分別從不同的視角來分析,加深我們的理解

從線程的角度理解Java Runtime Area

首先,我們從區(qū)域是否是線程私有的還是所有線程共享的來分類:

image.png

程序計(jì)數(shù)器 Java虛擬機(jī)棧 本地方法棧都是線程私有的

Java堆****方法區(qū)****運(yùn)行時(shí)常量池都是所有線程共享的

進(jìn)一步理解:

  • 對(duì)于線程私有的數(shù)據(jù)區(qū)域程序計(jì)數(shù)器 Java虛擬機(jī)棧 本地方法棧,他們的生存周期都是一致的,都是
    隨著線程開始,而進(jìn)行初始化
    隨著線程結(jié)束而銷毀

  • 而對(duì)于線程共享的數(shù)據(jù)區(qū)域Java堆****方法區(qū)****運(yùn)行時(shí)常量池,他們的生存周期都是一致的
    隨著JVM的啟動(dòng)而分配內(nèi)存
    隨著JVM的關(guān)閉而銷毀

從存儲(chǔ)內(nèi)容理解Java Runtime Area

下面我們?cè)俑鶕?jù)不同區(qū)域所存儲(chǔ)的數(shù)據(jù)類型進(jìn)行分類:
可以分為三類

  • 方法區(qū)和常量池存儲(chǔ)類的信息
  • 堆內(nèi)存存儲(chǔ)對(duì)象信息
  • 程序計(jì)數(shù)器,Java虛擬機(jī)棧,本地方法棧存儲(chǔ)線程的信息

下圖很清楚的說明

image.png

The heap space holds object data, the method area holds class code, and the native area holds references to the code and object data.
堆存儲(chǔ)object的data,方法區(qū)存儲(chǔ)class的信息和code,native區(qū)域存儲(chǔ)指向class信息和code的引用和指向?qū)ο蟮膁ata的引用

下面這個(gè)圖更詳細(xì)的指出了三個(gè)區(qū)域存儲(chǔ)的內(nèi)容:

image.png

下面我們通過一個(gè)實(shí)際代碼的例子,來說明;

看下面這段代碼:

image.png

這段代碼編譯之后,就存儲(chǔ)成如下這個(gè)樣子:

image.png

易混淆的Java Runtime Area 的問題

下面我們會(huì)對(duì)關(guān)于Java 運(yùn)行時(shí)數(shù)據(jù)區(qū)易混淆的問題進(jìn)行釋疑

方法區(qū)中究竟存儲(chǔ)了哪些信息?

棧中存放了局部變量表等與方法有關(guān)的信息,但方法中還有指令代碼這一重要內(nèi)容,它既沒有放在棧(Stack)中也沒放在堆(Heap)中,那它放在哪呢?
其實(shí),方法區(qū)中除了包括你所說的“已加載的類的基本信息、常量、靜態(tài)變量等”外,還包括編譯器編譯后的代碼,而且這應(yīng)該是方法區(qū)中主要的一部分,畢竟類中主要是方法和屬性,而類中的屬性,如果是實(shí)例域的話則新建對(duì)象后存儲(chǔ)在堆(Heap)中,靜態(tài)的話就如你所說存儲(chǔ)在方法區(qū)中,因此該區(qū)域中方法占主要部分,這應(yīng)該是此運(yùn)行時(shí)數(shù)據(jù)區(qū)稱為方法區(qū)的原因吧。

基本數(shù)據(jù)類型的成員變量放在jvm的哪塊內(nèi)存區(qū)域里?

比如

class{
private int i;
}

有的朋友可能因?yàn)榛緮?shù)據(jù)類型,就認(rèn)為存儲(chǔ)在棧中。但其實(shí)是存儲(chǔ)在堆中的,因?yàn)檫@是屬于對(duì)象的信息,每個(gè)對(duì)象都擁有不同的實(shí)例變量,這些實(shí)例變量都存儲(chǔ)在堆中,不管是基本數(shù)據(jù)類型還是引用數(shù)據(jù)類型
ava虛擬機(jī)棧是線程私有的,生命周期跟線程相同,每個(gè)方法調(diào)用的時(shí)候都會(huì)創(chuàng)建一個(gè)棧幀用于存儲(chǔ)局部變量表,操作數(shù)棧,動(dòng)態(tài)鏈接,方法出口等信息。每個(gè)方法調(diào)用的過程,就代表了一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過程,當(dāng)進(jìn)入一個(gè)方法時(shí),這個(gè)方法在棧中需要分配多大的內(nèi)存都是完全確定的,方法運(yùn)行時(shí)不會(huì)改變局部變量表的大小——《深入理解java虛擬機(jī)第二版》
很多java程序員一開始就被網(wǎng)上的一些教程所誤導(dǎo):基本數(shù)據(jù)類型放在棧中,數(shù)組和類的實(shí)例放在堆中。 這個(gè)說法不準(zhǔn)確,事實(shí)上,如上面的實(shí)例變量i,他是存放在java堆中。因?yàn)樗皇庆o態(tài)的變量,不會(huì)獨(dú)立于類的實(shí)例而存在,而該類實(shí)例化之后,放在堆中,當(dāng)然也包含了它的屬性i。
如果在方法中定義了int i = 0;則在局部變量表創(chuàng)建了兩個(gè)對(duì)象:引用i和0。 這兩個(gè)對(duì)象都是線程私有(安全)的。 比如定義了int[] is = new int[10]. 定義了兩個(gè)對(duì)象,一個(gè)是is引用,放在局部變量表中,一個(gè)是長(zhǎng)度為10的數(shù)組,放在堆中,這個(gè)數(shù)組,只能通過is來訪問,方法結(jié)束后出棧,is被銷毀,根據(jù)java的根搜索算法,判斷數(shù)組不可達(dá),就將它銷毀了。

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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