java對象的建立過程:html
對象的建立開始:java
虛擬機遇到new 關鍵字的時候,首先去常量池中尋找有沒有這個類的符號引用,而且檢查該引用的類是否已經被加載,解析,和初始化過,若是沒有則會先執行該類的加載過程, 在經過檢查後,虛擬機爲該新生對象分配內存。併發
分配內存:佈局
爲對象分配內存有倆種方式: spa
一種分配方式是「指針碰撞",在內存規整的時候,已使用的內存在一側,未使用的內存在一側時,中間爲指示器指針,這個時候的內存分配就是把指示器指針向未使用的區域移動至建立的對象大小相等的距離。.net
另外一種分配方式是「空閒列表」,當內存不規整時,虛擬機必須在不連續的內存空間尋找一塊適合對象大小的內存區域,並使用一個列表去維護建立的每個區域,並更新列表上的記錄。線程
選擇那種分配方式是由堆內存是否規整決定,又由所採用的gc是否帶有壓縮整理功能決定。
指針
當面臨併發時時,有可能存在,虛擬機給對象A分配內存時指針還將來得及改變,這個時候同時又有B對象使用指針來分配內存解決這個問題的兩種式:code
一種是對分配內存空間的操做進行同步處理 ,虛擬機採用的CAS(見http://www.blogjava.net/xylz/archive/2010/07/04/325206.html) 和失敗重試的方式保證更新操做的原子性,另外一種是把內存分配的動做按照線程劃分在不一樣的空間進行,即每個線程都在java堆中預先分配一小塊內存。又稱本地線程分配緩衝(Thread Local Allocation Buffer,簡稱TLAB)。 TLAB用完時分配新的TLAB 時須要同步鎖定操做。虛擬機設置使用TLAB,能夠經過-XX:+/UseTLAB參數設定。orm
初始化對象內存空間:
內存分配完成以後,虛擬機對該對象分到的內存空間初始化爲零值(除了對象頭),若是使用了TLAB ,這一工做也能夠提早至TLAB分配時進行。 初始化零值這一步也是爲何對象剛建立就可使用的緣由。
對象設置:
虛擬機對對象進行設置,好比對象是那個類的實例,對象的哈希值,gc分帶年齡等,這些信息都存在對象的頭之中。以後就是執行<init>方法,到此類建立結束。
java對象的內存佈局:
對象在內存中分三塊區域, 對象頭,實例數據,對齊填充。
java對象頭部分倆個部分:一部分是用來存對象自己的運行時數據,好比:哈希code, gc分帶年齡,鎖狀態標誌,線程持有的鎖,偏向線程ID,偏向時間戳等
另外一部分是類型的指針,指向類元數據,虛擬機經過這個指針肯定它屬於那個類的實例,查找對象的元數據信息,並不必定須要通過對象自己。
實例數據部分是對象真正存儲的有效信息,也是代碼中所定義的類型的字段內容,不管是父類仍是子類的都須要記錄。
對齊填充不是必然存在的,它只是起佔位符的做用,HotSpot VM的自動內存管理系統要求對象的起始地址必須是8字節的整數倍,若是不是則須要經過對齊填充來補全。
對象的訪問定位:
一種是經過句柄訪問,reference中存儲的是句柄地址,這種方式首先須要在java堆中劃分一塊內存做爲句柄池,這種方法的好處是,當對象指針發生改變好比:對象被移動,這個時候reference自己不須要改變。
另外一種是直接指針訪問,reference直接指向java堆中的類對象地址。對象訪問在java虛擬機中很頻繁,因此第一種方法會形成必定的開銷成本。