Java對象創建

        創建一個Java只要使用new關鍵字就可以,但是在我們new一個對象的時候,虛擬機中經歷的過程要比調用new關鍵字這一行代碼複雜的多。

        虛擬機遇到一個new指令時,先去常量池中檢查這個類是否被加載解析和初始化,如果沒有,則會先執行類加載過程。

        當類加載檢查通過後,虛擬機會爲新生對象分配內存空間。新生對象所需的內存大小在類加載完成後便可完全確定,爲對象分配空間的任務就是把一塊確定大小的內存從java堆中劃分出來。如果java堆的內存是規整的,已使用的內存放一邊,空閒的內存放領一邊,中間用一個指針作爲分隔,內存分配只要把這個指針移動與新生對象大小相等的距離即可(指針碰撞)。如果內存不是規整的,虛擬機要維護一個列表,記錄哪些內存塊是可用的,分配的時候從列表中找出一塊足夠大的空間分配給新生對象,並更新記錄(空閒列表)。

        對象的創建在虛擬機中是非常頻繁的,即時僅僅修改一個指針的位置,在多線程併發下也不是安全的。解決這個問題有兩種方法,一種是對內存空間的動作進行同步處理。另一種是把內存分配的動作按照線程劃分在不同的空間中進行,內個線程在java堆中預先分配一小塊內存,成爲本地線程分配緩衝區(TLAB),只有一個線程的TLAB用完了申請新的TLAB時才需要同步鎖定。

        內存分配完成後,虛擬機會將分配到的內存空間都初始化爲零值。Java中一個對象的成員變量聲明瞭沒有實例化,基本數據類型都爲0或false等初始值,對象因爲指針找不到對象會爲null。之後虛擬機會對對象進行必要的設置,因爲當前只是在內存空間申請了一塊內存空間,還有設置這個對象是哪個類的實例,對象的哈希碼,對象的GC分代年齡等信息。這些信息存放在對象的對象頭中。然後會調用新對象的<init>方法,此時一個對象纔算真正的創建完成。(new關鍵字執行完畢)

        對象在內存中存儲分爲3部分,對象頭,實例數據和對齊填充。頭包含兩部分,第一部分存儲對象自身的運行時數據,如哈希碼,GC年齡,鎖狀態標誌等信息,這部分數據的長度在32位和64位虛擬機中的大小分別是322bit和64bit。另一部分是類型指針,既標識這個對象是哪個類的實例。實例部分就是對象真正存儲的有效信息。第三部分對齊填充不是必須存在的,僅僅起佔位符的作用,因爲Java對象的起始地址必須是8字節的整數倍,也就是說對象的大小必須是8字節的整數倍,當實例數據沒有對齊時,要靠對齊填充來補全。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章