1. 程式人生 > >JVM記憶體結構(基於JDK8)

JVM記憶體結構(基於JDK8)

    根據VM規範,VM應該被劃分為五塊區域——即VM棧、堆、方法區、程式計數器、本地方法棧五個部分。如下圖所示:

    方法區(Method Area):該區域是所有執行緒共享的,主要用於存放類的資訊,常量、靜態變數、即時編譯器編譯後的程式碼等。垃圾回收器對這塊區域的回收主要是針對常量池和類的解除安裝。

    java堆(Java Heap):該區域也是所有執行緒共享的,用於存放物件例項,絕大多數建立的物件都會被存放到這裡(除了部分由於逃逸分析而在對外分配的物件,該部分只是在方法體被引用,故被分配到了棧上)。垃圾回收器最主要針對的物件,對這部分的回收效率影響了VM的整體效能。

    本地方法棧(Native Methiod Stack):該區域是每個執行緒鎖獨有的,主要用於VM的Native方法。這部分是有VM自行管理,程式設計師基本上不需要關係該部分。

    VM棧(VM Stack):該區域也是每個執行緒所獨有的,與本地方法棧是類似的,唯一的區別是它為VM執行Java方法服務。該區域主要維護棧針(每呼叫一個方法,則VM就會建立一個棧針保護當前方法的狀態,並將其壓入棧中,當被呼叫的方法完成後,在將其出棧繼續執行未完成的方法),有一定的深度,可能會丟擲StackOverflowError和OutOfMemoryError。

    程式記數器:該區域也是每個執行緒所獨有的,該區域主要是存放當前執行指令的地址。

   接下來給出基於JDK8的JVM的記憶體模型,如下圖所示:

    與VM規範的劃分並沒有特別大的改動,只是結合了java的具體實現改變了部分內容的存放位置。

     下面給出Java堆記憶體的區域劃分,如圖所示:

     Eden:該區域是最主要的剛建立的物件的記憶體分配區域,絕大多數物件都會被建立到這裡(除了部分大物件通過記憶體擔保機制建立到Old區域,預設大物件都是能夠存活較長時間的),該區域的物件大部分都是短時間都會死亡的,故垃圾回收器針對該部分主要採用標記整理演算法了回收該區域。

    Surviver:該區域也是屬於新生代的區域,該區域是將在Eden中未被清理的物件存放到該區域中,該區域分為兩塊區域,採用的是複製演算法,每次只使用一塊,Eden與Surviver區域的比例是8:1,是根據大量的業務執行總結出來的規律。

    Old:該區域是屬於老年代,一般能夠在Surviver中沒有被清除出去的物件才會進入到這塊區域,該區域主要是採用標記清除演算法。

    總結:java堆的垃圾回收是垃圾回收器最主要的光顧物件,整體採用分代收集的策略,對不同區域結合其特點採用不同的垃圾收集演算法。我們在程式設計中也應該關注這一塊區域,儘量不適用大物件,儘可能的建立區域性物件,使用過後確定廢棄不用的物件及時斷開引用,儘量避免使用迴圈的物件引用(可達性分析也是比較消耗資源的)等等。