JVM記憶體模型及分割槽
阿新 • • 發佈:2019-01-09
Java虛擬機器在程式執行過程會把jvm的記憶體分為若干個不同的資料區域來管理,這些區域有自己的用途,以及建立和銷燬時間。
jvm管理的記憶體區域包括以下幾個區域:
棧區:
棧分為java虛擬機器棧和本地方法棧
- 重點是Java虛擬機器棧,它是執行緒私有的,生命週期與執行緒相同。
- 每個方法執行都會建立一個棧幀,用於存放區域性變量表,操作棧,動態連結,方法出口等。每個方法從被呼叫,直到被執行完。對應著一個棧幀在虛擬機器中從入棧到出棧的過程。
- 通常說的棧就是指區域性變量表部分,存放編譯期間可知的8種基本資料型別,及物件引用和指令地址。區域性變量表是在編譯期間完成分配,當進入一個方法時,這個棧中的區域性變數分配記憶體大小是確定的。
- 會有兩種異常StackOverFlowError和 OutOfMemoneyError。當執行緒請求棧深度大於虛擬機器所允許的深度就會丟擲StackOverFlowError錯誤;虛擬機器棧動態擴充套件,當擴充套件無法申請到足夠的記憶體空間時候,丟擲OutOfMemoneyError。
- 本地方法棧 為虛擬機器使用到本地方法服務(native)
堆區:
- 堆被所有執行緒共享區域,在虛擬機器啟動時建立,唯一目的存放物件例項。
- 堆區是gc的主要區域,通常情況下分為兩個區塊年輕代和年老代。更細一點年輕代又分為Eden區最要放新建立物件,From survivor 和 To survivor 儲存gc後倖存下的物件,預設情況下各自佔比 8:1:1。
不過很多文章介紹分為3個區塊,把方法區算著為永久代。這大概是基於Hotspot虛擬機器劃分, 然後比如IBM j9就不存在永久代概論。不管怎麼分割槽,都是存放物件例項。 - 會有異常OutOfMemoneyError
方法區:
- 被所有執行緒共享區域,用於存放已被虛擬機器載入的類資訊,常量,靜態變數等資料。被Java虛擬機器描述為堆的一個邏輯部分。習慣是也叫它永久代(permanment generation)
- 垃圾回收很少光顧這個區域,不過也是需要回收的,主要針對常量池回收,型別解除安裝。
- 常量池用於存放編譯期生成的各種位元組碼和符號引用,常量池具有一定的動態性,裡面可以存放編譯期生成的常量;執行期間的常量也可以新增進入常量池中,比如string的intern()方法。
程式計數器:
- 當前執行緒所執行的行號指示器。通過改變計數器的值來確定下一條指令,比如迴圈,分支,跳轉,異常處理,執行緒恢復等都是依賴計數器來完成。
- Java虛擬機器多執行緒是通過執行緒輪流切換並分配處理器執行時間的方式實現的。為了執行緒切換能恢復到正確的位置,每條執行緒都需要一個獨立的程式計數器,所以它是執行緒私有的。
- 唯一一塊Java虛擬機器沒有規定任何OutofMemoryError的區塊
jvm分割槽大致就這個塊,具體裡面還有很多細節,及其各個模組工作的演算法都很複雜,這裡只是對分割槽進行簡單介紹,掌握一些基本的知識點。