JVM - Java 虛擬機器的記憶體劃分
本文章內容來自《深入理解jvm虛擬機器》一書,有興趣的同學可以看下這本書。
Java虛擬機器在執行Java程式的過程中會將自身所管理的記憶體劃分為若干個不同的資料區。這些區域都有各自的用途,以及建立和銷燬的時間。
記憶體模組大致如下(該圖依據《深入理解Java虛擬機器一書》)
列個表格介紹每個記憶體區域的作用以及生命週期
記憶體型別 | 作用 | 有無異常 | 佔用區域大小 | 建立時機&生命週期 | |
---|---|---|---|---|---|
程式計數器 | 記錄當前執行緒中程式執行的位置(大白話就是程式碼走到那一行了) | 無 | 較小 | 隨執行緒建立而建立,隨執行緒銷燬而銷燬,生命週期同線程。該區域是執行緒私有記憶體,各執行緒之間相互獨立。 | |
虛擬機器棧 | 用於承載java方法執行所建立的棧幀從入棧到出棧時所使用的資料(區域性變量表...) | OutOfMemoryError和StackOverflowError | -- | 執行緒私有,同程式計數器 | |
本地方法棧 | 與虛擬機器棧相似,只不過是本地方法的執行 | OutOfMemoryError和StackOverflowError | -- | 同虛擬機器棧 | |
Java 堆 | 存放物件例項(包含陣列) | OutOfMemoryError | 最大 | 執行緒共享,虛擬機器啟動時建立, | |
方法區 | 用於儲存已被虛擬機器載入的類資訊,常量,靜態變數,即時編譯器編譯後的程式碼資料等 | OutOfMemoryError | -- | 執行緒共享的記憶體區域 | |
執行時常量池 | 是方法區的一部分,用於存放編譯期生成的各種字面量和符號引用 | OutOfMemoryError | -- | -- |
有些表格沒有列出來的或者其他我需要知道的點,在下面的文字中進行描述
1. 程式計數器
當前執行緒所執行位元組碼的行號指示器,位元組碼指示器通過改變這個計數器的值來選取下一條位元組碼的指令來驅動程式的執行。
java虛擬機器的多執行緒是通過執行緒輪流切換並分配時間片的方式實現,任何一個確定的時刻,一個處理器都只會執行一條執行緒中的指令。
2. Java虛擬機器棧
虛擬機器棧描述的是Java方法執行的記憶體模型:每個方法在執行的同時會建立一個棧幀用於存放該方法執行時所需要的資料(區域性變量表、運算元棧、動態連結、方法出口等資訊)。每個方法從呼叫直至執行結束的過程,就對應著一個棧幀在虛擬機器棧中入棧到出棧的過程。
區域性變量表:
區域性變量表所存放的內容是編譯期可知的各種基本型別,物件引用型別。(這裡可以想一下平時寫方法時,方法所包含的內容,區域性變數(基本資料型別、引用型別、呼叫其他方法的返回值)也不知道這樣想對不對,有錯誤歡迎指正)
區域性變量表所需要的記憶體空間在編譯期間完成分配,當進入一個方法時,這個方法需要在棧幀中分配多大的區域性變數空間是完全確定的,在方法執行期間不會改變其大小。(講一個比較容易記的例子,把棧幀當做一個房子(不帶車庫,但是想買一輛車,需要根據車的尺寸建個車庫),這個區域性變量表比作車庫,那我建車庫的時候這些尺寸都是可已知的--有點不恰當,後面在組織下語言,先記著)
3. Java堆
Java堆是垃圾收集器管理的主要區域,可以是物理上不連續的記憶體空間,邏輯上連續即可。該區域既可以固定大小也可以進行擴充套件