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()方法)。