天天看點

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

1 Java Run Theory Analysis(Java運作原理分析)

  • 1.1 Class檔案結構
  • 1.2JVM運作時資料區簡介
  • 1.3 Class檔案内容解析,并JVM運作解析class檔案過程

1.1 Class檔案結構

學過Java的都知道,Java檔案先經過編譯器編譯成.class檔案,那麼.class檔案是怎麼樣的結構呢?

public class Helloworld {

        public static void main(String args[]){
            System.out.println("hello world!!!");
        }

}
           

這個Helloworld程式編譯成.class檔案之後,使用EditPlus以16進制打開,能看到檔案的開頭是以“CA FE BA BE”開頭的。這裡面還包括了版本、通路标志(public/private等)、常量池、目前類、父類、接口、字段、方法、屬性。

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

1.2JVM運作時資料區簡介

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

從這個圖可以看出編譯成.class檔案之後,由JVM來加載class檔案,并将class檔案的内容在JVM資料區中進行處理。

線程獨占:每個線程都會有它的獨立地空間,随線程生命周期而建立和銷毀

線程共享:所有線程能通路這塊記憶體資料,随虛拟機或GC(垃圾回收)而建立和銷毀

下面對JVM運作時資料區進行解釋:

1、方法區:JVM用來存儲加載的類資訊、常量、靜态變量、編譯後的代碼等資料,虛拟機規範中這是一個邏輯區域,不同的虛拟機其實作也是不同的,并且它是各個線程共享的記憶體區域。

如:oracle的HotSpot在JDK7中方法區放在永久代,JDK8則放在中繼資料空間,并且通過GC機制對這個區域進行管理。

2、堆記憶體:由老年代、新生代(細緻點可分為Eden、From Survivor、To Survivor),JVM啟動時建立,存放對象的執行個體。垃圾回收器主要就是管理堆記憶體。如果滿了,就會出現OutOfMemoryError。

3、虛拟機棧:每個線程都在這個空間有自己的私人空間,線程棧由多個棧幀(Stack Frame)組成。一個線程會執行一個或多個方法,一個方法對應一個棧幀。

棧幀的内容包括:局部變量表、操作數棧、動态連結、方法傳回位址、附加資訊等。棧記憶體預設最大是1M,超出則抛出StackOverflowError。

4、本地方法棧:與虛拟機棧類似,虛拟機棧是為虛拟機執行Java方法而準備的,本地方法棧是為虛拟機使用Native本地方法而準備的。虛拟機規範沒有規定具體的實作,由不同的虛拟機廠商去實作。HotSpot虛拟機中虛拟機棧和本地方法棧的實作是一樣的,超出大小之後會抛出StackOverflowError。

5、程式計數器:記錄目前線程執行位元組碼的位置,存儲是位元組碼指令位址,如果執行Native方法,則計數器值為空。每個線程都會在這個空間占據一定的私人空間,占用記憶體空間很小。CPU同一時間,隻會執行一條線程中的指令,JVM多線程會輪流切換并配置設定CPU執行時間的方式。為了線程切換後,需要通過程式計數器,來恢複正确的執行位置(說白了程式計數器就是記錄線程的執行位置的)。

1.3 Class檔案内容解析,并JVM運作解析class檔案過程

從一個最簡單的代碼開始:

public class Demo {
    public static void main(String args[]){
        int x = 100;
        int y = 200;
        int z = 200/100;
        System.out.println(x + y);
    }
}
           

使用javap –v Demo.class > Demo.txt就能夠将解析出來的内容重定向到Demo.txt中。

部分内容如下:

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

minor version:0 —次版本号

major version:49 —主版本号(49-JDK5->52-JDK8)

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

Constant pool:常量池

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

Demo的源碼中沒有定義構造函數,但是編譯完之後會有預設的無參構造函數。

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

具體指令,可以查指令碼表:

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

接下來,分析一下通過查指令表的指令,來分析以上執行過程

JVM Memory Model and Visibility(JVM記憶體模型與可見性)1.1 Class檔案結構1.2JVM運作時資料區簡介1.3 Class檔案内容解析,并JVM運作解析class檔案過程

首先,本地變量表中第0個參數是main方法中的args,bipush 100意思是先往棧中放入100,然後istore_1将100儲存在本地變量1,然後将200儲存在本地變量2,然後将常量值2入棧,存在本地變量3的位置,getstatic #2,擷取常量池(demo.txt中的Java版本号下面)中的#2常量(對應的也就是System.out.PrintStream),然後将變量表中的位置1的值壓入棧,位置2也壓入棧,執行加法操作(注意,這裡執行加法操作之後,棧中就剩下最後的結果300了,),invokevirtual(查詢指令表,“運作時方法綁定調用方法”),調用靜态方法,JVM會根據這個方法描述,建立新的棧幀,方法的參數從操作數棧中彈出,壓入虛拟機棧,然後虛拟機會開始執行虛拟機棧最上面的棧幀。執行完畢後,在執行main方法對應的棧幀。

最後輸出完之後,return,main方法也執行結束。

繼續閱讀