Java內存區域-讀書筆記《深刻理解java虛擬機》
運行時數據區域
程序計數器
- 能夠看做是當前線程所執行的字節碼的行號指示器
- 線程私有,每條線程都有獨立的程序計數器
- 惟一沒有OOM狀況區域(java虛擬機規範)
java虛擬機棧
- 線程私有
- 描述的是Java方法執行的內存模型
- 每一個方法執行時建立棧幀,用於存局部變量表、操做數棧、動態連接、方法出口等
- 局部變量表在編譯時完成分配
- 兩種異常
- StackOverflowError:棧深度超過規定
- OutOfMemoryError
本地方法棧
java堆
- 全部線程共享
- 也稱:GC堆
- 分爲:
- 邏輯上連續,物理上能夠不連續的內存空間
- -Xmx、-Xms控制
- 有OOM
方法區
- 全部線程共享
- 習慣稱爲:永久代,喜歡用永久代來實現方法區而已
- 用於存儲:
- 類信息
- 常量
- 靜態變量
- 即時編譯器編譯後的代碼
- 等等
- 有OOM
運行時常量池
- 方法區的一部分
- 用於存放編譯期生成的各類字面量和符號引用
- 不必定只有編譯期才能產生,運行時也可能,例:String.intern()方法
- 有OOM
直接內存
- DirectMemory
- 不是虛擬機運行時數據區一部分
- 也不是java虛擬機規範中定義的區域
- 有OOM
- 不受java堆大小限制
對象建立
給對象分配內存
- 指針碰撞:java堆中內存是絕對規整(已分配與空閒分別在兩邊)
- 空閒列表:不規整,必須維護一個列表,記錄哪些內存可用
- 併發狀況
- 分配時同步
- 每一個線程預先分配一塊內存(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使用
- 速度快
歡迎關注本站公眾號,獲取更多信息