Java內存區域-讀書筆記《深刻理解java虛擬機》

運行時數據區域

程序計數器

  • 能夠看做是當前線程所執行的字節碼的行號指示器
  • 線程私有,每條線程都有獨立的程序計數器
  • 惟一沒有OOM狀況區域(java虛擬機規範)

java虛擬機棧

  • 線程私有
  • 描述的是Java方法執行的內存模型
    • 每一個方法執行時建立棧幀,用於存局部變量表、操做數棧、動態連接、方法出口等
    • 局部變量表在編譯時完成分配
  • 兩種異常
    • StackOverflowError:棧深度超過規定
    • OutOfMemoryError

本地方法棧

  • native方法,相似java虛擬機棧

java堆

  • 全部線程共享
  • 也稱:GC堆
  • 分爲:
    • 新生代
    • 老年代
  • 邏輯上連續,物理上能夠不連續的內存空間
  • -Xmx、-Xms控制
  • 有OOM

方法區

  • 全部線程共享
  • 習慣稱爲:永久代,喜歡用永久代來實現方法區而已
  • 用於存儲:
    • 類信息
    • 常量
    • 靜態變量
    • 即時編譯器編譯後的代碼
    • 等等
  • 有OOM

運行時常量池

  • 方法區的一部分
  • 用於存放編譯期生成的各類字面量符號引用
  • 不必定只有編譯期才能產生,運行時也可能,例:String.intern()方法
  • 有OOM

直接內存

  • DirectMemory
  • 不是虛擬機運行時數據區一部分
  • 也不是java虛擬機規範中定義的區域
  • 有OOM
  • 不受java堆大小限制

對象建立

給對象分配內存

  • 指針碰撞:java堆中內存是絕對規整(已分配與空閒分別在兩邊)
    • 垃圾收集器帶壓縮整理
  • 空閒列表:不規整,必須維護一個列表,記錄哪些內存可用
    • 垃圾收集器:Mark-Sweep 標記清除
  • 併發狀況
    • 分配時同步
    • 每一個線程預先分配一塊內存(TLAB)
  • 分配完成後,內存空間初始化爲零值,若是是TLAB,可提早置TLAB時進行
    • 這就是對像實例字段不賦值也有初始值的緣由
  • 而後對對象進行必要的設置,如對象是哪一個類的實例等,存放在對象頭中

對象的內存佈局

  • 對象頭(Header)
    • 第一部分存儲對象自身的運行時數據
      • 哈希碼、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等
      • 這部分數據長度在32位和62位(未開啓壓縮指針)中分別是32bit和64bit
      • 官方稱爲:Mark Word
      • 非固定的數據結構
    • 另一部分是類型指針
      • 指向它的類元數據的指針,經過這個肯定是哪一個類的實例
      • 並非全部虛擬機實現都必須在對象數據上保留類型指針
    • 若是是數組,對象頭中還必須有一塊用於記錄數組長度的數據
  • 實例數據
    • 各類類型的字段內容
      • 父類中定義的變量出如今子類以前
      • 存儲順序受虛擬機分配策略參數(FieldsAllocationStyle)和在源碼中定義的順序影響
      • HotSpot虛擬機默認分配策略:
        • longs/doubles、ints、shorts/chars、bytes/booleans、oops
        • 相同寬度字段老是分配到一塊兒
  • 對齊填充
    • 不是必然存在的
    • 也沒有特別含義
    • 佔位符做用
    • 使對象大小必須爲8字節整數倍

對象訪問定位

  • 句柄訪問
    • java堆中分一塊內存做爲句柄池
      • 對象實例地址
      • 對象類型地址
    • 對象移動時,只需改變句柄中實例數據指針
  • 直接指針訪問
    • 堆對象中必須考慮如何放訪問類型數據相關信息
    • HotSpot使用
    • 速度快
相關文章
相關標籤/搜索