深刻剖析Java虛擬機內存結構

深刻剖析Java虛擬機內存模型

JVM總體架構

JVM總體架構以下:java

經過編寫代碼來分析整個內存區域架構

public class Math {
    public static final Integer CONSTANT = 666;

    public int compute(){
        int a = 1;
        int b = 2;
        int c = (a + b) * 10;
        return c;
    }

    public static void main(String[] args) {
        Math math = new Math();
        math.compute();
    }
}

對上述代碼的class文件進行javap - c Math.class > Math.txtjvm

javap -c是對代碼進行反彙編函數

獲得Math.txt文件命令行

對compute方法進行分析:code

public int compute();
    Code:
       0: iconst_1 //  將int型(1)推送至棧頂
       1: istore_1 //  將棧頂int型數值存入第二個本地變量
       2: iconst_2 //  將int型(2)推送至棧頂
       3: istore_2 //  將棧頂int型數值存入第三個本地變量
       4: iload_1 //   將第二個int型本地變量推送至棧頂
       5: iload_2 //   將第三個int型本地變量推送至棧頂
       6: iadd //      將棧頂兩int型數值相加並將結果壓入棧頂
       7: bipush        10 // 將單字節的常量值(-128~127)推送至棧頂
       9: imul // 將棧頂兩int型數值相乘並將結果壓入棧頂
      10: istore_3 // 將棧頂int型數值存入第四個本地變量
      11: iload_3 // 將第四個int型本地變量推送至棧頂
      12: ireturn

上面程序,在JVM中的運行時區域以下:對象

操做的操做暫時的數據存放到操做數棧blog

main()的局部變量表存放對象的引用地址。ip

動態連接

動態連接就是當咱們這個程序運行main方法時,當執行math對象額compute方法時,去compute方法執行,compute方法算是符號引用,找到符號引用所在的方法體,執行。內存

執行javap -v Math.class > Math.txt獲得字節碼文件

找到main方法所在的位置

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class com/tugohost/jvm/Math
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: invokevirtual #4                  // Method compute:()I
        12: pop
        13: return
      LineNumberTable:
        line 17: 0
        line 18: 8
        line 19: 13
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      14     0  args   [Ljava/lang/String;
            8       6     1  math   Lcom/tugohost/jvm/Math;

其中

9: invokevirtual #4 // Method compute:()I

這一行表示,main函數中的math對象調用compute方法,

再往上找,找到常量池

找到

#4 = Methodref          #2.#33         // com/tugohost/jvm/Math.compute:()I

再找#2#33

#2 = Class #32 // com/tugohost/jvm/Math
#3 = Methodref #2.#31 // com/tugohost/jvm/Math." ":()V

因此這個過程就是動態連接的過程。

本地方法棧

本地方法棧就是存儲native方法

若是Eden區放滿,會minor GC,若是還存活的對象,會放到From區生命值+1,同理會放到To區生命值+1,若是生命值大於某個值(能夠本身設置),會放到老年代

經過寫一個死循環代碼來看看堆中垃圾收集器的工做:

public class HeapTest {
    byte[] a = new byte[1024 * 100]; // 100Kb

    public static void main(String[] args) throws InterruptedException {
        ArrayList<HeapTest> heapTests = new ArrayList<>();
        while (true){
            heapTests.add(new HeapTest());
            Thread.sleep(10);
        }
    }
}

經過命令行jvisualvm打開Java visualVM

若是老年代滿了觸發Full GC。若是Full GC對老年代沒有用,即老年代中沒有無用的對象時,出現OOM效果。

相關文章
相關標籤/搜索