JVM 運行時數據區 (三)

JVM運行時數據區

運行時數據區由 程序計數器、java虛擬機棧、本地方法棧、堆、方法區 組成;java

一、程序計數器

  每個Java線程都有一個程序計數器,用於保存程序執行到當前方法的哪個指令,它是線程私有的。函數

此內存區域是惟一一個在VM Spec中沒有規定任何OutOfMemoryError狀況的區域。spa

 

二、Java虛擬機棧

  一般說的棧指的就是Java棧,主管Java程序的運行。棧是在線程建立時建立,線程結束棧內存就釋放掉了,不存在垃圾回收問題,線程一結束該棧就Over,與程序計數器同樣,它的生命週期也是與線程相同,它是線程私有的線程

  基本類型的變量、實例方法、引用類型變量都是在函數的棧內存中分配3d

  棧描述的是Java方法調用的內存模型:每一個方法被執行的時候,都會同時建立一個幀(Frame)用於存儲本地變量表、操做棧、動態連接、方法出入口等信息。每個方法的調用至完成,就意味着一個幀在VM棧中的入棧至出棧的過程。本地變量表存放了編譯期可知的各類標量類型(boolean、byte、char、short、int、float、long、double)、對象引用(不是對象自己,僅僅是一個引用指針)、方法返回地址等指針

  這個區域規定了2種異常:若是線程請求的棧深度大於虛擬機所容許的深度,將拋出StackOverflowError異常;若是VM棧能夠動態擴展(VM Spec中容許固定長度的VM棧),當擴展時沒法申請到足夠內存則拋出OutOfMemoryError異常。code

(1)拋出StackOverflowError異常的代碼(遞歸調用):對象

public class StackDemo1
{
    static void sayHello()
    {
        System.out.println("AAAAA");
        sayHello();
    }

    public static void main(String[] args) {
        sayHello();
    }
}

 

三、本地方法棧

  本地方法棧和Java虛擬機棧發揮的做用是相似的,只不過Java虛擬機棧爲虛擬機運行原語服務,而本地方法棧是爲虛擬機使用到的 native 服務。blog

它的實現語言、結構、方式沒有強制規定,甚至有的虛擬機把它和java虛擬機棧合二爲一了,例如Sun Hotspot遞歸

  和java虛擬機棧同樣,這個區域也會拋出StackOverflowError異常和OutOfMemoryError異常。

 

四、堆

  Java7以前

    一個JVM實例只存在於一個堆內存中,堆內存的大小是能夠調節的。類加載器讀取了類文件以後,須要把類、方法、常變量放到堆內存中,

  保存全部引用類型的真實信息,以方便執行器執行。

    堆內存邏輯上分爲:新生區、養老區、永久區。(實際上永久區被稱爲非堆內存)

    新生區:伊甸區(Eden Space)、倖存0區(Survivor 0 Space)、倖存1區(Survivor 1 Space)

    當new 一個對象,該對象被放入伊甸區(Eden),建立的對象愈來愈多,伊甸區(Eden)快滿的時候啓動一種輕垃圾回收(Minor GC),未被回收的對象被放入倖存0區(Survivor 0),Eden被清空;當倖存0區快滿了,未被回收的對象被放入倖存1區(Survivor 1),Survivor 0和Eden被清空;Survisor 0與Survivor 1交換角色,如此循環往復。若是對象的複製次數達到16次,該對象就會被送到養老中。當養老區快滿的時候觸發一個重量級的GC(Major GC),清理以後仍是沒法再保存對象,就會產生OOM異常(OutOfMemoryError)。

    Survisor 0 和 Survivor 1會一直調換角色,誰是空的誰就是Survivor 1區。

         

    

    

五、方法區

  方法區是全部線程共享的,一般用來儲存裝載的類的元結構信息。垃圾回收不多發生;

  好比:運行時常量池 + 靜態變量 + 常量 + 字段 + 方法字節碼 + 在類/實例/接口初始化用到的特殊方法等。

  一般和永久區關聯在一塊兒(Java7),具體的跟JVM的實現和版本有關。Java8之後,變爲了MetaSpace(元空間),直接使用的物理內存,垃圾回收運行的機率變得更低。

相關文章
相關標籤/搜索