【Java虛擬機】對象的創建過程

1 檢查是否已加載

接受到new指令時,首先將區檢查這個指令的參數是否能在常量池中定位到一個類的符號引用,並檢查這個俄富豪引用代表的類是否已被加載、解析和初始化。如果沒有,則執行類加載過程。

2分配內存

首先對象所需的內存大小,是完全確定的,不會隨着實例的不同而變化,個人認爲,是因爲變量數量、變量大小都是固定的,即使有可變的string、List等變量,在類中存儲的也僅僅是一個指針,大小總是相等的。

分配內存的方式
方式一:指針碰撞: 假設堆中的內存絕對規整,一邊全部是用過的,另一邊全部是空閒的,中間放着一個指針作爲指示器,則內存的分配只需要將指針移動一段距離即可。
方式二:空閒列表: 如果內存不規整,使用過的內存和空閒內存交錯在一起,就無法使用簡單的指針碰撞了,虛擬機必須維護一個列表,記錄哪塊內存可用,然後找到一個足夠大的內存塊分配給新對象,並更新列表上的記錄。

選取那種方式,有java堆是否規整決定。 是否規整,則又取決於垃圾收集器是否帶有空間壓縮整理。 帶有空間壓縮整理的垃圾收集器有:Serial、ParNew;不帶壓縮整理的:CMS(基於清除算法)

擴展問題:如何保證線程安全?
方法一:同步處理:利用CAS和失敗重試保證更新操作的原子性
方法二:本地線程分配緩衝(ALAB):給每個線程在堆中預先分配一塊內存,從而保證不同線程之間互不影響。詳情見:什麼是對象分配過程中的TLAB?

3 初始化零值

內存分配完成後,虛擬機必須將分配到內存的空間(不包括對象頭),都初始化爲零值。保證對象的實例字段在jva代碼中可以不賦值就直接使用。

4 必要的設置

如:

  • 對象是哪個類的實例
  • 如何才能找到類的元數據信息
  • 對象的哈希碼
  • 對象的GC分代年齡信息

至此,從虛擬機的視角來看,一個新的對象已經產生!

5 接下來的事情

從java程序的視角來看,對象的創建纔剛剛開始。接下來還要執行構造函數等方法,按照程序員的意願堆對象進行初始化,這樣一個真正的可用對象纔算完全 被構造出來。

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