對象的建立
HotSpot虛擬機中,當咱們使用new關鍵字建立一個對象的時候,虛擬機會作以下的操做:數組
- 查看方法區中的常量池是否能定位到對象類的符號引用,而且檢查這個引用是否被加載過、解析和初始化過,若是沒有,將先執行類加載;
- 爲對象分配內存空間;
- 設置對象頭;
- 執行數據初始化;
爲對象分配內存空間可能有兩種方式:安全
- 指針碰撞(Bump the pointer):當內存是絕對規整時,按內存的連續性分配內存,以一個指針標記當前已用內存和空閒內存的邊界
- 空閒列表(Free List):當內存不規整時,虛擬機須要維護一張列表,記錄哪些內存可用
內存是否規整取決於所採用的垃圾回收器,在內存分配時還須要考慮線程安全問題,解決方案有:佈局
- 對分配內存的動做進行同步處理;
- 把內存分配的動做按照線程劃分紅不一樣的空間中進行,每一個線程在Java堆中預先分配一小塊內存,稱爲本地線程分配緩衝(Thread Local Allocation Buffer, TLAB),能夠用參數-XX:+UseTLAB啓用
對象的內存佈局
- 對象頭(Header):分爲兩部分,第一部分用於存儲對象運行時數據,如哈希碼、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等,官方叫作Mark Word;另外一部分是類型指針,即對象指向它的類型數據的指針;另外若是是一個數組對象,對象頭中還必須有數組的長度;
- 實例數據(Instance Data)
- 對齊填充(Padding)
對象的訪問定位
目前主流的訪問方式有使用句柄和直接指針:spa
- 使用句柄:將在Java堆中劃分出一塊內存來做爲句柄池,引用中存放的就是句柄的位置,句柄中存儲了對象的類型指針和對象地址的指針;優點:當垃圾回收時,對象可能被移動,自動後只須要修改句柄中的地址
- 直接指針:引用中直接放的對象的地址,對象的類型經過對象頭信息找到;優點:速度更快,節約了一次指針定位的時間