1. 程式人生 > >java堆上的物件

java堆上的物件

Java堆上的物件

1.物件的建立(new Object)

  • 建立過程:先檢查能否在常量池中定位到一個類的符號引用,並且檢查其代表的類是否被載入、解析和初始化過;若無,執行類載入過程;然後為新生物件分配記憶體(類載入完成後即可確定物件大小);記憶體分配完後,記憶體空間初始化為零;接下來,對物件的類資訊、類的元資料資訊、物件雜湊碼、GC分代年齡進行設定(這些資訊存放在物件頭中(Object Header));然後執行<init>方法(按照程式設計師的意願進行初始化)
  • java堆上記憶體分配的兩種方式:”指標碰撞“(中間一個指標作為空閒記憶體和用過記憶體的分界點)、”空閒列表“(列表記錄哪些記憶體塊可用),採用哪種方式取決於垃圾收集器是否帶有壓縮整理功能。 分配記憶體時考慮執行緒安全問題:CAS失敗重試,或者使用本地執行緒分配緩衝(TLAB)(類似於ThreadLocal)

2.物件的記憶體佈局

  • 3個區域:物件頭(Header)、例項資料(Instance Data)和對齊填充(Padding).
  • 物件頭; 兩部分資訊:第一部分用於儲存物件自身的執行時資料,如雜湊碼、GC分代年齡、鎖狀態標誌、執行緒持有鎖、偏向執行緒ID、偏向時間戳等;另一部分是型別指標,即物件指向類元資料的指標。 如果物件是Java陣列,物件頭中需要記錄陣列長度

3.物件的訪問定位

通過棧上reference資料來操作,主流的訪問方式兩種:

  • 控制代碼:reference儲存的是控制代碼地址,控制代碼池中的控制代碼包含了物件例項資料和型別資料的地址資訊
  • 直接指標訪問:reference中存放的直接就是物件地址。
  • 對比:控制代碼方式穩定,物件移動時,只需改變控制代碼中的例項資料指標,reference不用變;直接指標方式速度更快,因為節省了一次指標定位的時間開銷。Sun HotSpot使用指標方式。

String.intern()是一個Native方法,作用:若字串常量池中已經包含了一個等於String物件的字串,則返回代表池中這個字串的String物件;否則,將此String物件包含的字串新增到常量池中,並且返回此String物件的引用。
StirngBuilder建立的字串例項在Java堆上。