JVM記憶體劃分

2021-07-08 19:49:24 字數 1213 閱讀 6515

從上圖可以看出,jvm記憶體區域可以簡單的劃分為方法區,堆區,虛擬機器棧,本地方法棧和程式計數器。上圖中,淺色的為執行緒共有的記憶體區域,深色的為執行緒私有的記憶體區域。

可以看出,方法區和堆區是所有執行緒之間共享的記憶體區,而棧區和pc則是執行緒本身私有的,不能被其他執行緒所共享。我們簡單的說下各個區域:

程式計數器:學過組成原理和作業系統的話,我們都知道其中有乙個pc,用來告訴cpu執行什麼指令。在jvm中,也是類似的,只不過這裡的指令不是作業系統級別,而是jvm的,它可以看作當前執行緒所執行的位元組碼的行號指示器。每個執行緒都有乙個程式計數器去執行下乙個執行指令的位址。此pc不包括native方法。這是唯一乙個沒有記憶體溢位異常的記憶體區域。

虛擬機器棧:執行緒私有的記憶體區域,其生命週期和執行緒自身保持一致,棧區描述的是執行緒內方法執行的記憶體模型,執行緒在執行方法的時候,都會建立乙個棧幀,用於儲存區域性變數表,運算元棧,動態鏈結,方法出口等資訊。每次的方法呼叫都對應著乙個棧幀在虛擬機器棧的入棧和出棧操作。區域性變數表存放了各種編譯期可知的區域性變數,如基本型別和物件引用等。區域性變數表的記憶體空間在編譯期間完成記憶體分配,當進入乙個方法時,此方法所需棧幀的區域性變數大小是確定的,不會在執行期間改變。這裡引用下葛一鳴書中的定義:區域性變數表是棧幀的重要組成部分之一,用於儲存函式的引數,函式內部的區域性變數等。區域性變數表中的變數只在當前函式有效,當函式的呼叫結束後,隨著區域性變數表的銷毀而銷毀。

周志明書中說到,區域性變數表的記憶體大小在編譯器就已經決定了這是可以理解的,至少在編譯器,我們就已經知道了函式的形參型別,方法內部的變數個數 等等,完全可以決定記憶體大小。

本地方法站棧:對應於native方法。

方法區:執行緒共享的記憶體區域,用於儲存已經載入的類資訊,常量,靜態變數,即時編譯後的**資料等。jvm虛擬機器規範把方法區描述為堆區的乙個邏輯部分。在jdk1.6 和1.7中,方法區可以理解為perm永久區,在jdk1.8中,永久區被徹底移除,取而代之的是元資料區,是一塊堆外的直接記憶體。如果不指定大小,會耗盡jvm所有可用系統記憶體。

方法區還包含執行時常量池,用於存放執行時產生的常量。比如string.intern()方法。

直接記憶體:不是jvm虛擬機器定義的記憶體區域,但也被頻繁使用。比如nio,引入了一種基於通道與緩衝區的io方式,可以使用native函式直接在堆外分配記憶體,然後通過堆中diectbytebuffer作為這塊記憶體的引用進行操作。

參考至周志明 葛一鳴書籍。

JVM 記憶體劃分總結

總結 1 所有執行緒共享的記憶體資料區 方法區,堆。而虛擬機器棧,本地方法棧和程式計數器都是執行緒私有的。2 存放於棧中的東西如下 2.1 每個執行緒包含乙個棧區,棧中只儲存基礎資料型別的物件和自定義物件的引用 不是物件 物件都存放在堆區中。2.2 每個棧中的資料 基礎資料型別和物件引用 都是私有的...

JVM的記憶體區域劃分

jvm的記憶體區域劃分 在j a語言當中,記憶體是如何劃分的呢?由於j a程式是交由jvm執行的,所以我們在談j a記憶體區域劃分的時候事實上是指jvm記憶體區域劃分。在討論jvm記憶體區域劃分之前,先來看一下j a程式具體執行的過程 如上圖所示,首先j a源 檔案 j a字尾 會被j a編譯器編譯...

jvm記憶體模型 JVM記憶體模型詳情解析

一 結構圖 note string常量池 存在 堆記憶體中 二 各部分詳情解析 1 堆1 老年代 物件年齡 經過一次 monitor gc 年齡加1 15 的會存到 老年代 2 年輕代 3 常量池 string常量 儲存在堆中 2 虛擬機器棧 1 區域性變數表 2 運算元棧 3 動態鏈結 4 方法出...