JVM 內(nèi)存區(qū)域介紹

作者博客地址: http://gudong.name
本文博客地址: http://gudong.name/2017/04/14/jvm_vs_dalvik.html

Java虛擬機(jī)在執(zhí)行Java程序的過程中,會把它所管理的內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū)域。這些區(qū)域都有各自的用途,以及創(chuàng)建、銷毀的時間,有的區(qū)域空間隨著虛擬機(jī)進(jìn)程的啟動而分配,有些區(qū)域則是依賴用戶線程,他們隨著線程的啟動和結(jié)束而建立和銷毀。

Java 虛擬機(jī)管理的內(nèi)存包括以下幾個運(yùn)行時數(shù)據(jù)區(qū)域,如圖所示


{D431DF9A-9278-D045-49B5-F6AD12BC9FE9}.png

可以看到有五部分組成,下面分別介紹

程序計數(shù)器

程序計數(shù)器(Program Counter Register)是一塊較小的內(nèi)存空間,它的作用可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。在虛擬機(jī)的概念模型里(僅是概念模型,各種虛擬機(jī)可能會通過一些更高效的方式去實(shí)現(xiàn)),字節(jié)碼解釋器工作時就是通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個計數(shù)器來完成。

由于Java虛擬機(jī)的多線程是通過線程輪流切換并分配處理器執(zhí)行時間的方式來實(shí)現(xiàn)的,在任何一個確定的時刻,一個處理器(對于多核處理器來說是一個內(nèi)核)只會執(zhí)行一條線程中的指令。因此,為了線程切換后能恢復(fù)到正確的執(zhí)行位置,每條線程都需要有一個獨(dú)立的程序計數(shù)器,各條線程之間的計數(shù)器互不影響,獨(dú)立存儲,我們稱這類內(nèi)存區(qū)域?yàn)椤熬€程私有”的內(nèi)存。

Java 虛擬機(jī)棧

Java虛擬機(jī)棧 與程序計數(shù)器一樣,Java虛擬機(jī)棧(Java Virtual Machine Stacks)也是線程私有的,它的生命周期與線程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法被執(zhí)行的時候都會同時創(chuàng)建一個棧幀(Stack Frame[插圖])用于存儲局部變量表、操作棧、動態(tài)鏈接、方法出口等信息。每一個方法被調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機(jī)棧中從入棧到出棧的過程。

以前經(jīng)常說 Java 內(nèi)存分為堆內(nèi)存和棧內(nèi)存,這其實(shí)是一種不嚴(yán)謹(jǐn)?shù)恼f法,這里說的堆內(nèi)存沒問題,但是棧內(nèi)存,其實(shí)就是這里的 Java 虛擬機(jī)棧,或者說是虛擬機(jī)棧中的局部變量表。

局部變量表

局部變量表應(yīng)該是一個典型的棧,他存放了編譯期可知的各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型,它不等同于對象本身,根據(jù)不同的虛擬機(jī)實(shí)現(xiàn),它可能是一個指向?qū)ο笃鹗嫉刂返囊弥羔?,也可能指向一個代表對象的句柄或者其他與此對象相關(guān)的位置)和returnAddress類型(指向了一條字節(jié)碼指令的地址)。

怎么理解呢?比如現(xiàn)在正在執(zhí)行一個方法,方法中定義了各種變量,

void test(){
  int age = 0;
  String name = "mao"
  Person person = new Person(age, name);
}

這時方法 test 在虛擬機(jī)中執(zhí)行時,age name 這種基本數(shù)據(jù)類型會直接存放在局部變量表中,而 person 這種引用類型變量只會在局部變量表中存放一個引用指針,具體 person 的內(nèi)存分配并不在局部變量表中分配,而是在后面講到的 Java 堆中分配。

JVM 規(guī)范中規(guī)定了 Java 虛擬機(jī)棧 可能會發(fā)生兩種異常:當(dāng)線程請求的棧深度大于虛擬機(jī)所允許的深度,則拋出 StackOverflowError; 如果虛擬機(jī)可以動態(tài)擴(kuò)展,擴(kuò)展到到無法申請更多的內(nèi)存會拋出 OOM 。

本地方法棧

關(guān)于本地方法棧,這里可以拿上面剛講到的虛擬機(jī)棧做一下對比。
虛擬機(jī)棧為虛擬機(jī)執(zhí)行 Java 方法而服務(wù),本地方法棧則是為虛擬機(jī)使用到的 Native 方法服務(wù)。其余跟 Java 虛擬機(jī)棧并沒有什么特別的區(qū)別。所以對應(yīng)的異常拋出機(jī)制,跟虛擬機(jī)棧一致。

Java 堆

至此你會發(fā)現(xiàn),上面說到的三個區(qū)域:程序計數(shù)器,Java 虛擬機(jī)棧、本地方法棧都是線程私有。

但是跟上面三種不一樣,Java 堆是所有線程共享的一片區(qū)域,他隨著一個 Java 虛擬機(jī)實(shí)例的創(chuàng)建而分配好。該區(qū)域存在的唯一目的就是存放對象,幾乎應(yīng)用中所有的對象實(shí)例都在這里分配內(nèi)存(非絕對)。

因?yàn)樯厦嫒N內(nèi)存空間為線程私有,他們隨線程生而生,隨線程死而死,所以這三中空間一般不需要執(zhí)行垃圾回收,所以我們我們通常說的垃圾回收大多都發(fā)生在 Java 堆。

從內(nèi)存回收角度講,現(xiàn)在的垃圾收集器大都采用分代收集法。所以根據(jù)此可以把 Java 堆分為新生代和老年代

對新生代又可以細(xì)分為 Eden 空間、From Survivor 空間、To Survivor 空間。

根據(jù) Java 虛擬機(jī)規(guī)范,Java 堆可以處與物理上不連續(xù)的內(nèi)存空間中。只要邏輯連續(xù)即可。一般的 Java 堆都被設(shè)計成可擴(kuò)展的。如果堆中沒有內(nèi)存分配實(shí)例,并且堆也無法擴(kuò)展時,將會拋出 OutOfMemmoryError.

方法區(qū)

與Java堆一樣,方法區(qū)(Method Area)是各個線程共享的內(nèi)存區(qū)域,它用于存儲已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。

雖然Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個邏輯部分,但是它卻有一個別名叫做Non-Heap(非堆),目的應(yīng)該是與Java堆區(qū)分開來。

Java 虛擬機(jī)規(guī)范規(guī)定,該區(qū)域可以不實(shí)現(xiàn)垃圾回收。因?yàn)橄鄬Χ裕@個區(qū)域垃圾回收行為比較少見,但是并非數(shù)據(jù)進(jìn)入方法區(qū)就一直不回收了。

這個區(qū)域的內(nèi)存回收目標(biāo)主要是針對常量池的回收和對類型的卸載。

運(yùn)行時常量池

運(yùn)行時常量池是方法區(qū)的一部分。

這里先說說一般的 class 文件,即一個 .java 文件編譯后成為字節(jié)碼文件 .class . Class 文件中除了有類的版本,字段,方法,接口,等描述信息,還有一項(xiàng)信息是常量池。

Class 文件中的常量池用于存放編譯期生成的各種字面量和符號引用。這部分內(nèi)容將在類加載后存放在方法區(qū)的運(yùn)行時常量池。

這里對 Class 文件常量池和 JVM 運(yùn)行時常量池 進(jìn)行一下區(qū)別。

這兩是兩個不同的概念,前者其實(shí)是一個物理上的概念,當(dāng)我們的 .java 文件編譯成 .class 文件后,該區(qū)域已經(jīng)在 .class 文件中占據(jù)了固定的位置。這一點(diǎn)你可以通過查看具體的 .class 文件得到。而當(dāng)這個 class 文件加載到 JVM 中后,Class 文件常量池中的信息將會全部存放在 JVM 方法區(qū)的運(yùn)行時常量池。所以前者是實(shí)實(shí)在在存在的,而后者是一個 JVM 中的內(nèi)存區(qū)域,兩者存在一個簡單的對應(yīng)關(guān)系。

運(yùn)行時常量池相對于 Class 文件常量池的一個重要特征就是前者具備動態(tài)性,運(yùn)行時常量池可以在程序運(yùn)行期間動態(tài)的把新的常量放入運(yùn)行時常量池。

線程私有的個人理解

//TODO

參考

JVM 垃圾回收

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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