轉(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)一般如下圖所示:

由上圖可知JVM基本機構(gòu)包括:類加載器、內(nèi)存區(qū)域、執(zhí)行引擎、本地庫接口 。
這里我們說明一下內(nèi)存區(qū)(也叫運行時數(shù)據(jù)區(qū)),運行時內(nèi)存區(qū)主要可以劃分為5個區(qū)域:
- JVM棧 (Java Virtual Machine Stacks)
- 堆內(nèi)存 (Heap Memory)
- 方法區(qū) (Method Area)
- 本地方法棧 (Native Method Stacks)
- 程序計數(shù)器 (Program Counter (PC) Register)
接下里就詳細說明一下這些區(qū)域的區(qū)別:
- 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ū)(存放操作指令)。
- 堆內(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)存,存取速度較慢。
- 方法區(qū) (Method Area)
在方法區(qū)中,存儲了每個類的信息(包括類的名稱、方法信息、字段信息)、靜態(tài)變量、常量以及編譯器編譯后的代碼等。
在Class文件中除了類的字段、方法、接口等描述信息外,還有一項信息是常量池,用來存儲編譯期間生成的字面量和符號引用。
在方法區(qū)中有一個非常重要的部分就是運行時常量池,它是每一個類或接口的常量池的運行時表示形式,在類和接口被加載到JVM后,對應(yīng)的運行時常量池就被創(chuàng)建出來。
當然并非Class文件常量池中的內(nèi)容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,比如String的intern方法。雖然JVM規(guī)范把方法區(qū)描述為堆的一個邏輯部分, 但它卻有個別名non-heap(非堆)。
- 本地方法棧 (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棧合二為一。
- 程序計數(shù)器 (Program Counter (PC) Register)
用于保存當前線程執(zhí)行的內(nèi)存地址。
由于JVM程序是多線程執(zhí)行的(線程輪流切換),所以為了保證線程切換回來后,還能恢復(fù)到原先狀態(tài),就需要一個獨立的計數(shù)器,記錄之前中斷的地方,可見程序計數(shù)器也是線程私有的。
注意這個區(qū)域是唯一一個不拋出OutOfMemoryError的運行時數(shù)據(jù)區(qū)。