JVM內(nèi)存模型

轉(zhuǎn)https://blog.csdn.net/heart_mine/article/details/79495032

在介紹jvm的堆、棧、方法區(qū)的區(qū)別之前需要先了解一下JVM的基本結(jié)構(gòu)是什么。

根據(jù)《java虛擬機規(guī)范》規(guī)定,JVM的基本結(jié)構(gòu)一般如下圖所示:

image.png

由上圖可知JVM基本機構(gòu)包括:類加載器、內(nèi)存區(qū)域、執(zhí)行引擎、本地庫接口 。

這里我們說明一下內(nèi)存區(qū)(也叫運行時數(shù)據(jù)區(qū)),運行時內(nèi)存區(qū)主要可以劃分為5個區(qū)域:

    1. JVM棧 (Java Virtual Machine Stacks)
    1. 堆內(nèi)存 (Heap Memory)
    1. 方法區(qū) (Method Area)
    1. 本地方法棧 (Native Method Stacks)
    1. 程序計數(shù)器 (Program Counter (PC) Register)

接下里就詳細說明一下這些區(qū)域的區(qū)別:

    1. JVM棧 (Java Virtual Machine Stacks)

每當啟動一個新線程的時候,java虛擬機都會為它分配一個java棧。java以棧幀為單位保存線程的運行狀態(tài)。虛擬機只會對java棧執(zhí)行兩種操作:以棧幀為單位的壓?;蛘叱鰲?。

每個線程包含一個棧區(qū),棧中只保存基礎(chǔ)數(shù)據(jù)類型的對象和自定義對象的引用(不是對象),對象都存放在堆區(qū)中 。

每個棧中的數(shù)據(jù)(原始類型和對象引用)都是私有的,其他棧不能訪問。

棧分為3個部分:基本類型變量區(qū)、執(zhí)行環(huán)境上下文、操作指令區(qū)(存放操作指令)。

    1. 堆內(nèi)存 (Heap Memory)

存儲的全部是對象,每個對象包含一個與之對應(yīng)的class信息–class的目的是得到操作指令。

jvm只有一個堆區(qū)(heap)被所有線程共享,堆區(qū)中不存放基本類型和對象引用,只存放對象本身。

堆的優(yōu)勢是可以動態(tài)地分配內(nèi)存大小,生存期也不必事先告訴編譯器,因為它是在運行時動態(tài)分配內(nèi)存的,Java的垃圾收集器會自動收走這些不再使用的數(shù)據(jù)。

缺點是,由于要在運行時動態(tài)分配內(nèi)存,存取速度較慢。

    1. 方法區(qū) (Method Area)

在方法區(qū)中,存儲了每個類的信息(包括類的名稱、方法信息、字段信息)、靜態(tài)變量、常量以及編譯器編譯后的代碼等。

在Class文件中除了類的字段、方法、接口等描述信息外,還有一項信息是常量池,用來存儲編譯期間生成的字面量和符號引用。

在方法區(qū)中有一個非常重要的部分就是運行時常量池,它是每一個類或接口的常量池的運行時表示形式,在類和接口被加載到JVM后,對應(yīng)的運行時常量池就被創(chuàng)建出來。

當然并非Class文件常量池中的內(nèi)容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,比如String的intern方法。雖然JVM規(guī)范把方法區(qū)描述為堆的一個邏輯部分, 但它卻有個別名non-heap(非堆)。

    1. 本地方法棧 (Native Method Stacks)

和java棧的作用差不多,只不過是為JVM使用到的native方法服務(wù)的。

Java官方對于本地方法的定義為methods written in a language other than the Java programming language,就是使用非Java語言實現(xiàn)的方法,但是通常我們指的一般為C或者C++,因此這個棧也有著C棧這一稱號。一個不支持本地方法執(zhí)行的JVM沒有必要實現(xiàn)這個數(shù)據(jù)區(qū)域。本地方法?;竞蚃VM棧一樣,其大小也是可以設(shè)置為固定值或者動態(tài)增加,因此也會對應(yīng)拋出StackOverflowError和OutOfMemoryError錯誤。

在HotSopt虛擬機中直接就把本地方法棧和Java棧合二為一。

    1. 程序計數(shù)器 (Program Counter (PC) Register)

用于保存當前線程執(zhí)行的內(nèi)存地址。

由于JVM程序是多線程執(zhí)行的(線程輪流切換),所以為了保證線程切換回來后,還能恢復(fù)到原先狀態(tài),就需要一個獨立的計數(shù)器,記錄之前中斷的地方,可見程序計數(shù)器也是線程私有的。

注意這個區(qū)域是唯一一個不拋出OutOfMemoryError的運行時數(shù)據(jù)區(qū)。

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

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