1. 程式人生 > >JVM 記憶體模型:方法區(Method Area)

JVM 記憶體模型:方法區(Method Area)

1. 前言

最近在研究Java語言底層基礎知識,發現對於JVM 記憶體模型理解不夠深入。筆者突發奇想深入理解JVM記憶體模型,特在此介紹詳細介紹一下JVM記憶體模型中的方法區。看似名稱叫做方法區,其實不然。它存放了一些類載入基本資訊、常量、靜態變數以及編譯後的程式碼等資料。下面我們來詳細看一下其中的內容。執行時常量池也可以包含再方法區中,執行時常量池存放的是編譯期間生成的各種字面量以及符號引用。關於字面量與符號引用的知識,筆者不再詳細介紹。

2. 方法區

方法區是執行緒共享的,它儲存已經被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等等。(HotSpot虛擬機器上開發部署人員更願意成為“永久代”,Permanent Generation)。示意圖如下:
在這裡插入圖片描述

1. 型別資訊

  • 型別的全限定名
  • 超類的全限定名
  • 直接超介面的全限定名
  • 型別標誌(該類是類型別還是介面型別)
  • 類的訪問描述符(public、private、default、abstract、final、static)

2.型別的常量池

存放該型別所用到的常量的有序集合,包括直接常量(如字串、整數、浮點數的常量)和對其他型別、欄位、方法的符號引用。常量池中每一個儲存的常量都有一個索引,就像陣列中的欄位一樣。因為常量池中儲存中所有型別使用到的型別、欄位、方法的字元引用,所以它也是動態連結的主要物件(在動態連結中起到核心作用)。

3. 欄位資訊(該類宣告的所有欄位)

  • 欄位修飾符(public、protect、private、default)
  • 欄位的型別
  • 欄位名稱

4.方法資訊

方法資訊中包含類的所有方法,每個方法包含以下資訊:

  • 方法修飾符
  • 方法返回型別
  • 方法名
  • 方法引數個數、型別、順序等
  • 方法位元組碼
  • 運算元棧和該方法在棧幀中的區域性變數區大小
  • 異常表

5.類變數(靜態變數)

指該類所有物件共享的變數,即使沒有任何例項物件時,也可以訪問的類變數。它們與類進行繫結。

6.指向類載入器的引用

每一個被JVM載入的型別,都儲存這個類載入器的引用,類載入器動態連結時會用到。

7.指向Class例項的引用

類載入的過程中,虛擬機器會建立該型別的Class例項,方法區中必須儲存對該物件的引用。通過Class.forName(String className)來查詢獲得該例項的引用,然後建立該類的物件。

8.方法表

為了提高訪問效率,JVM可能會對每個裝載的非抽象類,都建立一個數組,陣列的每個元素是例項可能呼叫的方法的直接引用,包括父類中繼承過來的方法。JVM對每個載入的非虛擬類的型別資訊中都添加了一個方法表,方法表是一組對類例項方法的直接引用(包括從父類繼承的方法)

9.執行時常量池(Runtime Constant Pool)

常量池,用於存放編譯器生成的各種字面常量和符號引用,這部分內容被類載入後進入方法區的執行時常量池中存放。執行時常量池相對於Class檔案常量池的另外一個特徵具有動態性,可以在執行期間將新的常量放入池中(典型的如String類的intern()方法)。