一:jvm的五大內存區(內存結構)


  jvm五大內存區域(即jvm運行時數據區),描述的是類被加載時,經過解析后,存儲到特定的數據區。方法區和堆是所有線程共享的,而棧和計數器是線程私有的。棧處理程序運行的問題,堆處理數據的存儲問題。所以才有堆棧分離。

方法區:又被稱為永久代,用來存儲類的信息,例如:方法,方法名,返回值,常量。當它無法滿足內存分配需求時,方法區會拋出OutOfMemoryError。

:存放new出來的對象信息, 全局變量。

程序計數器:指向當前線程正在執行的行號,用來保證線程切換時回到程序調用的位置。(例如:在a方法里面掉用了b方法,代碼從上往下執行,執行到掉用b方法的那行時,指針會記錄下這個位置,然后執行b方法里面的邏輯,b方法正常執行完或異常退出,指針都會回到a方法里面。)

案例:我們這里可以寫一個java文件,通過javac命令編譯生成一個class文件,然后通過javap -l 命令查看程序的行號和局部變量表。

虛擬機棧:描述的是線程進棧出棧的過程,線程結束內存自動釋放。它用來存儲當前線程運行方法所需要的數據、指令、返回地址。(即局部變量和正在調用的方法)     方法被調用時會在棧中開辟一塊叫棧幀的空間,方法運行在棧幀空間中。

先進后出:main方法先入棧,然后程序從上往下執行,a 和 b 相繼入棧,程序執行完之后出棧,可以看到main方法最后執行完,所以棧是先進后出的。

public class Test {

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

    public static void a(){
        b();
        System.out.println("a...");
    }

    public static void b(){
        System.out.println("b...");
    }
}

==========  控制台輸出  ===========

b...
a...
main...

棧幀的邏輯內存圖里面包含局部變量表,操作數棧,動態鏈接,出口...(注意:棧幀里面包含但不僅僅只有這些, 程序員開發主要是關注這些 )。  

public static void demo(){
    /**
     * 【局部變量表】 存放該方法的參數變量,和方法內部定義的局部變量,若該變量為引用類型,則存的該變量的引用地址。在java文件編譯成.class文件的時候,這個表的容量最大值就確定下來了。
     */
    String a = "局部變量a";
    String b = "局部變量b";
    int c = 2,d = 3; // 局部變量c和d
    /**
     * 【操作數棧】 也稱為表達式棧,通過字節碼指定把值壓入棧定,稍后另一個指令就可以彈出這個值使用。
     */
    int e = c*d; // 操作數棧
    /**
     * 【動態鏈接】 也稱為常量池。用來保存常量值和符號引用。符號引用:A方法在運行時調用B方法,就是通過B方法的符號引用去找到B的內存地址.)
     */
    UserDao dao = new UserDao();
    dao.insert(a);
    /**
     * (出口):描述的就是出棧的過程。方法的返回有兩種情況。(正常退出時:根據方法的定義來決定是否要傳返回值給上層調用者。異常退出時:則是需要通過異常處理來確定。無論通過哪種方式退出,都會跳到當前方法被調用的位子。
     */
}

* 如果線程請求的棧深度⼤大於虛擬機所允許的深度,將拋出 StackOverflowError 異常

 本地方法棧:和虛擬機棧類似,只是它描述的是為虛擬機是用到的Native方法出棧和入棧的過程(通常我們不需要了解這塊,它底層是C語言實現的)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM