Java內存區域——虛擬機運行時數據區

1. 環境說明:jdk1.7

2. 運行時數據區概況

    Java虛擬機在執行Java程序的過程中會把它所管理的內存分爲若干個不同的區域,我們將這些區域統稱爲運行時數據區域,如下圖所示。(深色表示線程共享內存區域,淺色表示線程私有內存區域)

                             

  2.1 程序計數器

    程序計數器可以理解爲當前線程所執行的字節碼的行號指示器,字節碼解釋器通過改變程序計數器的值來選取下一條需要執行的字節碼指令。由於Java虛擬機多線程是通過線程輪流切換並分配處理器時間的方式實現的,爲了保證線程切換後能恢復到正確的位置,每條線程都需要有一個獨立的程序計數器,這類內存區域稱爲“線程私有”的內存(上圖中使用白色表示)。如果線程正在執行一個Java方法,程序計數器記錄的是正在執行的字節碼指令的地址。如果線程正在執行一個native方法(native方法是指不使用Java代碼實現,使用本地庫實現的方法,例如dll動態鏈接庫文件 詳細信息可見 Java native方法),計數器值爲空。這部分內存不會發生OutOfMemory error。

  2.2 Java虛擬機棧

   Java虛擬機棧描述的是Java方法執行的內存模型,通常我們粗略地說Java內存被劃分爲堆和棧,儘管這樣的說法不具有一定的正確性,但此處的棧指的是Java虛擬機棧。每個方法執行時會在棧上創建一個棧幀(stack frame),用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息,當方法執行結束時,棧幀從虛擬機棧上出棧。在這些信息中,局部變量表中存放着各種基本數據類型、對象引用和returnAddress類型(指向一條字節碼指令的地址,用於返回),其中,long和double類型的數據佔據2個局部變量空間(slot),其餘數據佔用一個slot。這些數據所佔用的內存空間在編譯期間確認並完成分配。當線程請求的棧深度大於虛擬機所允許的深度時,將拋出StackOverflow error。當棧的內存空間不足時,將拋出OutOfMemory error。

  2.3 本地方法棧

  本地方法棧和虛擬機棧類似,只不過虛擬機棧描述Java方法執行的內存模型,爲虛擬機執行Java方法提供服務,而本地方法棧爲native方法執行提供服務(2.1中已提到native方法)。有的虛擬機例如hotspot,直接將本地方法棧和虛擬機棧合二爲一。

  2.4 Java堆

  Java堆區是Java虛擬機所管理內存中最大的一塊,被所有線程共享(圖中表示爲深色),幾乎所有的對象實例都在堆中分配內存。同時,Java堆是垃圾收集器管理的主要區域,從分代收集的內存回收策略上講,Java堆可以分爲年輕代和老年代。年輕代又可以細分爲Eden space、from survivor space和to survivor space。從內存分配的角度上講,Java堆可能被劃分爲多個線程私有分配緩衝區(Thread Local Allocation Buffer, TLAB),這樣有利於內存分配或者更加方便內存回收。

   重要的一點是,Java堆可以處於物理上不連續的內存空間,只要邏輯上連續即可(類似於硬盤空間的使用)。在實現上,Java堆一般是可擴展的(通過參數-Xms:初始heap大小,-Xmx:最大heap大小進行實現),當內存不足時,將拋出OutOfMemory異常。

  2.5 方法區

    方法區也是線程共享的內存空間,用於存儲被虛擬機加載的類信息、常量、靜態變量(static 說明見3.4)等,垃圾回收在這部分內存很少出現,但不意味着不對其進行垃圾回收,該部分內存垃圾回收相較於堆區更加困難,效果難以令人滿意(主要針對類型的卸載和常量池的回收)。

    2.5.1 運行時常量池

    運行時常量池是方法區的一部分,用於存儲類信息中的常量池(包括編譯期生成的各種字面量和符號引用)和直接引用(直接引用和符號引用見3.5)。跟用於存儲類信息的Class文件中的常量池相比,運行時常量池具備動態性,在運行期間也可以將新的常量放入池中,例如String類的intern()方法(見3.3)。

3. 補充知識

  3.1 native方法:參考資料 Java native方法

  3.2 this和super:static方法中不能使用this變量和super關鍵字,參考資料 Java中this和super的總結

  3.3 String類的intern()方法:String s調用該方法時,如果運行時常量池中存在一個字符串常量equals(s),則返回該字符串常量;如果不存在這樣的字符串常量,則將該字符串加入運行時常量池並且返回該字符串的指針。

  3.4 static關鍵字:簡單的說,如果一個變量或者方法是類的特性,與類的實例變量無關,我們將其聲明爲static。這樣在需要用到它們時不需要創建一個類的實例也能使用。參考資料 Java中static作用及用法詳解

  3.5 直接引用和符號引用:參考資料 JVM中的直接引用和符號引用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章