天天看點

JVM運作時記憶體區域、堆記憶體分段機制

作者:運維木子李

#暑期創作大賽#

JVM運作時記憶體區域、堆記憶體分段機制

JVM(Java虛拟機)運作時記憶體區域可以分為以下幾個部分:

方法區(Method Area):

用于存儲類的結構資訊,例如類的位元組碼、常量池、靜态變量、方法的位元組碼等。在JDK 8及之前,方法區被實作為永久代(Permanent Generation),而在JDK 8及以後的版本中,方法區被替換為元空間(Metaspace)。

示例:

public class MyClass {
    // 靜态變量
    public static int myStaticVar = 10;

    // 靜态方法
    public static void myStaticMethod() {
        System.out.println("This is a static method.");
    }

    // 執行個體變量
    public int myInstanceVar = 20;

    // 執行個體方法
    public void myInstanceMethod() {
        System.out.println("This is an instance method.");
    }

    public static void main(String[] args) {
        MyClass.myStaticMethod();

        MyClass obj = new MyClass();
        obj.myInstanceMethod();
    }
}           

在上面的示例中,靜态變量和靜态方法存儲在方法區中,而執行個體變量和執行個體方法則在堆中的對象執行個體中。

堆(Heap):

用于存儲對象執行個體。堆是JVM中最大的一塊記憶體區域,它是所有線程共享的。堆被分為新生代(Young Generation)和老年代(Old Generation)。新生代進一步被分為Eden區、Survivor區(通常有兩個)。

示例:

public class MyClass {
    public static void main(String[] args) {
        MyClass obj1 = new MyClass();
        MyClass obj2 = new MyClass();
        MyClass obj3 = new MyClass();

        // 輸出對象的哈希碼,用于表示對象在記憶體中的位址
        System.out.println(obj1);
        System.out.println(obj2);
        System.out.println(obj3);
    }
}           

在上面的示例中,通過new關鍵字建立了三個MyClass的對象執行個體。這些對象執行個體存儲在堆中,并且每個對象執行個體都有一個唯一的位址(即哈希碼)。

Eden區:

新建立的對象首先會被配置設定到Eden區。當Eden區滿時,觸發一次新生代的垃圾回收,存活的對象會被複制到Survivor區。

Survivor區:

存活的對象經過幾次垃圾回收後,會被移動到Survivor區。Survivor區主要用于存放新生代中存活的對象。當Survivor區滿時,存活的對象會被複制到另一個Survivor區,同時會清空目前Survivor區。

public class MyClass {
    public static void main(String[] args) {
        byte[] bytes1 = new byte[1024 * 1024];
        byte[] bytes2 = new byte[1024 * 1024];
        byte[] bytes3 = new byte[1024 * 1024];

        // 輸出堆中三個數組的位址
        System.out.println(bytes1);
        System.out.println(bytes2);
        System.out.println(bytes3);
    }
}           

在上面的示例中,通過建立三個大小為1MB的位元組數組,展示了堆記憶體中新生代的劃分。這些位元組數組首先會被配置設定到Eden區,當Eden區滿了之後,會觸發一次新生代的垃圾回收,存活的對象會被複制到Survivor區。下一次垃圾回收時,存活的對象會被複制到另一個Survivor區,并清空目前Survivor區。這個過程不斷重複,直到對象在Survivor區經過多次垃圾回收後仍然存活,它們會被晉升到老年代。

老年代:

經過多次垃圾回收後仍然存活的對象會被移動到老年代。老年代主要用于存放長期存活的對象。

棧(Stack):

每個線程在運作時都會建立一個棧。棧用于存儲方法調用的資訊、局部變量、方法參數等。每個方法在執行時都會建立一個棧幀,棧幀包含了方法的局部變量和操作數棧等資訊。棧是一個線程私有的記憶體區域。

本地方法棧(Native Method Stack):

類似于棧,但是用于執行本地方法(非Java代碼)。

PC寄存器(Program Counter Register):

存儲目前線程執行的位元組碼指令位址。

堆外記憶體(Off-heap Memory):

不在JVM堆中的記憶體,通常用于存儲大量的資料或與本地庫進行互動。

繼續閱讀