java內存總結

Java虛擬機管理的內存的區域可由下面這張圖表示
2012101820014328.jpg

這些內存區域可以劃分為線程私有和線程共享兩類:

  • 線程私有即是指該內存區域與線程同生共死,且該區域僅對該線程可見.
  • 線程共享則是指該內存區域隨虛擬機啟動而開辟,隨虛擬機關閉而釋放,且該區域對所有線程可見.

線程私有

  • 程序計數器:
    一塊小的內存區域,是當前線程所執行的字節碼的行號指示器.
    當實行java方法時,值為虛擬機字節碼指令地址;執行native方法時,值為空.
  • 虛擬機棧:
    從對應關系來看,一個線程對應一個虛擬機棧,而線程的一個方法對應虛擬機棧中的一個棧幀.可表現為下圖:


    無標題.png

    一個棧幀中儲存了一個方法的局部變量表,操作數棧,動態鏈接,方法出口等.
    線程調用一個方法即是一個棧幀入棧,結束一個方法即是一個棧幀出棧.

  • 本地方法棧:
    與虛擬機棧的結構,作用類似,不同的是虛擬機棧執行的是java方法,本地方法棧執行的是native方法.
    注:有的虛擬機將二者合二為一.

線程共享

  • java堆:
    用于存放對象實例和數組.
  • 方法區:
    用于存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據.
    方法區中包含運行時常量池,Class文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項信息是常量池,用于存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載后存放到方法區的運行時常量池中。
  • 直接內存:
    并不是虛擬機運行時數據區的一部分,也不是Java虛擬機規范中定義的內存區域.(堆外內存)


    無標題.png

一個實例對象被創建的過程如下圖所示:

IMG_20170720_132011.JPG

對象的內存布局

  • 對象頭
    對象頭包括兩部分信息,第一部分用于存儲對象自身的運行時數據,如哈希碼 (HashCode),GC分代年齡,鎖狀態標志,線程持有的鎖,偏向線程ID,偏向時間戳等.
    對象頭的另外一部分是類型指針,即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例。
    另外,如果對象是一個Java數組,那在對象頭中還必須有一塊用于記錄數組長度的數據,因為虛擬機可以通過普通Java對象的元數據信息確定Java對象的大小,但是從數組的元數據中卻無法確定數組的大小。
  • 實例數據
    實例數據部分是對象真正存儲的有效信息,也是在程序代碼中所定義的各種類型的字段內存。無論是從父類繼承下來的,還是在子類中定義的,都需要記錄起來。
  • 對齊填充
    對象的大小必須是8字節的整數倍,當不符合時,由占位符填充來保證.

對象的訪問定位

引用有兩種:

  • 句柄:
    句柄包含了對象實例指針和對象類型指針


    927608-20160702110103187-956075011.png
  • 直接指針:
    對象頭中有對象類型指針


    927608-20160702110119593-1353417498.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容