1. 程式人生 > >二、Java虛擬機器自動記憶體管理機制、執行時資料區域深入瞭解

二、Java虛擬機器自動記憶體管理機制、執行時資料區域深入瞭解

執行時資料區域:
    (1)、程式計數器
        a、定義:是一塊較小的記憶體空間,可以看作是當前執行緒所執行的位元組碼的行號指示器。
        b、執行緒私有:因為多執行緒是通過執行緒輪流切換並且分配處理器執行時間的方式來實現的,任何時刻,
            一個處理器都只會執行一條執行緒中的指令。執行緒切換後要恢復到正確的執行位置,所以每條執行緒
            都有一個獨立的程式計數器。互不影響,獨立儲存。
        c、執行緒執行java方法,計數器才會記錄位元組碼的地址,native方法計數器值是undefined。
        d、記憶體區域是唯一一個在java虛擬機器中是沒有任何OutOfMemoryError情況的區域。
    (2)、java虛擬機器棧


        a、執行緒私有,生命週期與執行緒相同。
        b、java虛擬機器棧描述的是java方法執行的動態記憶體模型。
        c、方法執行中建立一個棧幀:儲存區域性變量表,運算元棧,動態連結,方法出口燈資訊。
            一個方法的執行完成,其實就是java虛擬機器中一個棧幀在java虛擬機器中的入棧到出棧過程。
        d、棧深度大於虛擬機器最大深度拋StackOverflowError.
        e、棧無限制動態擴充套件,eg:方法中死迴圈,會拋OutOfMemoryError。
    (3)、本地方法棧
            a、本地方法棧描述的是native方法執行的動態記憶體模型。
            b、沒有語言資料結構強制規定,甚至sun hotspot虛擬機器把本地方法棧和java虛擬機器棧合二為一。
            c、會丟擲StackOverflowError,OutOfMemoryError。
    (4)、Java堆(Java Heap)

        a、java堆是所有執行緒共享的一塊區域,虛擬機器啟動時候建立。
        b、用處:存放物件例項。幾乎所有的物件例項都是在這裡分配記憶體。(不是所有)
        c、也是垃圾收集器的主要區域,也被稱為“GC堆”。 
    (5)、方法區(Method Area)
        a、方法區與堆一樣,是各個執行緒共享的記憶體區域,它用來儲存已經虛擬機器載入的類資訊,常量,靜態變數,
            即時編譯器編譯的程式碼等資料。別名:Non-Heap(非堆)。
            class檔案的資訊(類的資訊):類版本,欄位,方法,介面。
        b、方法區和永久帶並不是恆等,不同型別的虛擬機器規範不一樣;
        c、垃圾回收再方法區很少出現,主要是針對常量池的回收和對型別的解除安裝。回收效率不是很高。
        d、方法區無法滿足記憶體分配需求時,將丟擲OutOfMemoryError異常。
    (6)、執行時常量池(Runtime Constant Pool)

        a、RCP是方法區的一部分。
        b、class檔案(還有一個資訊)的常量池(Constant Pool Table)存放編譯器生成的各種字面量和符
            號引用,這部分內容將在類載入後進入方法區的執行時常量池中存放。
        c、執行時常量池相對於Class檔案常量池具備動態性。
            執行期間也可能將新的常量放入執行時常量池中,並非預置入Class檔案中的常量池才能進入RCP。
            eg:String 類中的intern()方法。               
        d、java虛擬機器規範對Class檔案每一部分有嚴格的規定,而對執行時常量池,沒有作嚴格細節要求。
    (7)、直接記憶體
        a、直接記憶體並不是虛擬機器執行時資料區的一部分,也不是Java 虛擬機器規範中農定義的記憶體區域。
        b、在JDK1.4 中新加入了NIO(New Input/Output)類,引入了一種基於通道(Channel)與緩衝區(Buffer)的I/O 方式,
            它可以使用native函式庫直接分配堆外記憶體,然後通脫一個儲存在Java堆中的DirectByteBuffer 物件作為這塊記憶體
            的引用進行操作。這樣能在一些場景中顯著提高效能,因為避免了在Java堆和Native堆中來回複製資料。本機直接內
            存的分配不會受到 Java 堆大小的限制,受到本機總記憶體大小限制配置虛擬機器引數時,不要忽略直接記憶體 防止出現
            OutOfMemoryError異常。
        c、byte byffer可以是兩種型別,一種是基於直接記憶體(也就是非堆記憶體);另一種是非直接記憶體(也就是堆記憶體)。
            對於直接記憶體來說,JVM將會在IO操作上具有更高的效能,因為它直接作用於本地系統的IO操作。而非直接記憶體,
            也就是堆記憶體中的資料,如果要作IO操作,會先複製到直接記憶體,再利用本地IO處理。
        d、從資料流的角度,非直接記憶體是下面這樣的作用鏈:
            本地IO-->直接記憶體-->非直接記憶體-->直接記憶體-->本地IO
            而直接記憶體是:  本地IO-->直接記憶體-->本地IO