2、虛擬機對象的建立
(一)對象建立的過程java
- 首先嚐試在常量池中查找相應類的信息,若查不到則加載類
- 接下來爲對象在堆中分配空間(對象分配的空間大小在類加載是已肯定),這裏有兩種分配方式:在虛擬機內存規整的時候使用指針碰撞(把指針向空閒空間挪動必定位置),在內存不規整時使用空閒類表(即維護一個列表,記錄哪些空間是可用的,在分配時找一塊足夠大的內存分配給對象)
- 再分配空間是須要考慮併發問題,經常使用的處理方法有兩種:第一種是採用CAS加失敗重試的方法分配內存;第二種是爲線程分配本身獨有的本地緩衝(TLAB,這樣只需在分配緩衝的時候須要處理併發,是否啓用TLAB能夠經過虛擬機參數設置)
- 接下來爲對象設置對象頭(Object Header),對象頭中存儲Hash碼,年齡帶等信息
- 虛擬機級別的對象建立完成
(二)對象在內存中的佈局數組
- 對象在內存中儲存的佈局分三部分:對象頭(存放Hash碼、年齡帶、鎖狀態標誌等),實例數據(java類中的屬性等),對其補充
- 對象頭:對象頭中除了存儲上述信息,還有一部分是實例的類型指針(即虛擬機經過這個指針肯定對象是哪一個類的實例);若此對象是數組,那麼還須要存儲數組長度
- 實例數據:存儲類中各個字段的值(不管是父類的仍是本身的),存儲的順序按照字段類型的寬度進行排序,可能子類寬度較窄的字段插在父類字段之間(能夠經過CompactFields=false,使子類的字段必定排在父類後邊)
- 對其補充:因爲虛擬機自動內存管理系統要求,對象的起始地址必須爲8的整數倍個字節,因此不是8的整數倍,須要補充,這個區域沒有什麼實際意義
(三)對象的訪問併發
- 虛擬機訪問對象有兩種方式:使用句柄,直接指針
- 使用句柄:在java堆中劃出一部分區域做爲句柄池,reference中存的就是對象的句柄地址,句柄地址中包含指向實例數據的指針和指向類型數據的指針
- 直接指針:reference中存儲的直接就是實例的地址,實例中存放指向類型數據的指針
- 使用句柄的好處在於當實例數據常常移動時(垃圾回收)只需改變句柄中實例數據的指針便可,而使用直接指針的好處在於速度快,在訪問對象(java就是對於對象的操做)時節省了一次調用指針的開銷
歡迎關注本站公眾號,獲取更多信息