1. 程式人生 > >JAVA物件建立的過程

JAVA物件建立的過程

JVM物件建立的過程
    對於java程式設計師來說,我們無時無刻不在建立和使用物件。使用new關鍵字即可快速建立一個物件,其實在new的背後,JVM為我們完成了很多事情。
    JVM的位元組碼直譯器在讀取到NEW的指令時,會先去常量區定位對應類的符號引用, 並且檢查符號引用指向的類的資訊有沒有被載入,解析和初始化過。如果沒有則會先進行類的載入過程。
    在對類的檢查通過後, JVM會去JAVA堆中進行物件的記憶體分配,物件的記憶體大小是在類載入後就能提前完全確定的。在JAVA堆中有兩種方式分配物件的記憶體空間:如果JAVA堆的記憶體空間是規整的,即所有用過的記憶體放在一邊,未使用過的記憶體放在另外一邊, 而中間則是一個指標作為分界線的指示器,分配物件的記憶體空間就相當於把指標往未使用過的記憶體那一邊挪一點已知物件大小空間,這種方式就叫做”指標碰撞”; 而對於記憶體空間不規整的JAVA堆來說, 則需要有一個空閒列表,存放可以使用的記憶體空間的地址, 當分配記憶體時, 需要從空閒列表裡取出一塊合適大小的記憶體地址分配給物件,然後更新空閒列表即可。一般比如Serial、ParNew等自帶壓縮整理功能的收集器則使用指標碰撞的方式分配物件空間, 還有一些比如CMS這種使用標記清除演算法功能的收集器則使用空閒列表的方式進行物件記憶體空間分配。
    虛擬機器中建立物件是非常頻繁的行為, 因此也要考慮併發的問題。假如在給某個指標指向的物件分配記憶體空間並且還未來得及修改指標時,另一個執行緒又修改了該指標所指向的物件,這個就是併發問題。解決這個問題有兩種方案:一種是在物件修改時進行同步鎖定處理,保證更新操作的原子性。還有一種方式是使用本地執行緒緩衝(Thread Local Allcation Buffer),簡稱TLAB, 即在JAVA堆中為每個執行緒劃分出一塊私有的記憶體區域,每個執行緒只在自己的緩衝區域進行物件建立。只有當TLAB需要擴充套件時才進行同步鎖定處理。虛擬機器是否使用TLAB,可以通過-XX:+/-UseTLAB引數來設定。
    當物件記憶體分配完畢後, 虛擬機器還需要對物件使用到的記憶體空間進行零值設定。這一操作在使用TLAB的虛擬機器中, 可以提前在TLAB中完成, 提高物件建立的速度。這個零值設定是確保JAVA物件在未初始化欄位值時也可以使用。
    接下來虛擬機器還需要進行物件頭資訊的設定, 例如一些物件的類資訊、雜湊碼、GC分代年齡資訊等。這一系列動作完成後, 對於虛擬機器來說,一個物件的建立就完成了。
    但是對於JAVA程式來說, 物件在建立完成後還需要執行init方法, 根據程式設計師的設定對物件進行一些資料的初始化,這樣一個物件的建立才真正的完成。