Java虛擬機——對象的創建、對象的內存佈局、對象的訪問定位 簡述

1:Java對象的創建

 

  •  判斷是否已經執行類加載

     當虛擬機遇到一條new指令時 ,首先去檢查這個指令的參數是否能在常量池中定位到一個類的符號引用,並且檢查這個符號引用代表的類是否已經被加載、解析和初始化過,如果沒有,那必須先執行相應的類加載過程。 

  •  內存分配

 當已經執行過類加載過程後,會爲新對象在Java堆中分配一個大小已經確定的內存,具體的內存分配規則有兩種:

  1. 指針碰撞(Bump the Pointer)
    如果Java堆中的內存是絕對規整的,所有用過的內存放一邊,空閒的內存放到一邊,中間放着指針爲分界點,分配內存就是把指針向空閒的一邊挪動一段與對象大小相等的距離。見圖1
  2. 空閒列表 (Free List )
    如果Java堆中的內存並不是規整對的,已使用的內存和空間相互交錯,虛擬機會將可以用的內存維護到一個列表上,在分配內存時從這個列表中找到一塊足夠大的空間劃給對象。然後更新列表記錄。

                                                                  圖1

Java堆中的內存是否是規整的是根據虛擬機所採用的垃圾收集器是否帶有壓縮整理功能決定的。Serial、ParNew帶壓縮整理的分配內存用指針碰撞,CMS這種通常用空閒列表方式分配內存

防止併發

在虛擬機上創建對象是非常頻繁的行爲,所以要做到防止併發,有以下兩種方式可實現:

  1. 堆分配內存空間的動作進行同步處理,實際上JVM採用CAS(Cmpare And Set)配上失敗重試的方式保證更新操作的原子性;
  2. 把內存分配的動作按照線程劃分在不同的空間之中進行,即爲每個線程在java堆中預先分配一塊小內存,稱爲本地線程分配緩衝區(Thread Local Allocation Buffer,TLAB)。分配內存時在線程的TLBA上分配,只有TLAB用完並分配新的TLAB時,才需要同步鎖定。JVM是否使用TLAB可以通過-XX:+UseTLAB參數來設定。

初始化對象內存空間 

   內存分配完成後,JVM將分配到的內存空間都初始化爲零值(不包括對象頭)。

對象頭的設置

將對象的類、哈希碼、對象的GC分代年齡等信息設置到對象頭之中。

對象的內存佈局

創建完對象後,對象對分配給自己的內存是如何佈局的呢?下面來介紹一下。

對象在堆內存中的佈局可分爲三部分:對象頭(Header)實例數據(Instance Data)對齊填充(Padding)

對象頭:對象頭包含兩部分,第一部分存儲自身運行時數據,如哈希碼,GC分代年齡、鎖狀態標誌、線程持有鎖、偏向線程ID、偏向時間戳等,官方稱爲“Mark Word”。

第二部分是類型指針,即對象指向它的類元數據的指針,通過此指針來確定是哪個類的對象。

實例數據存儲的是真正有效數據,如各種字段內容,各字段的分配策略爲longs/doublesints、 shorts/chars,bytes/booleanoops(ordinary object pointers),相同寬度的字段總是被分配到 ⼀起,便於之後取數據。⽗類定義的變量會出現在⼦類定義的變量的前⾯。

對齊填充:並不是必然存在的,當對象實例數據部分沒有對齊時,進行對齊補全。分僅僅起到佔位符的作⽤

對象的訪問定位

   Java程序需要通過棧上的reference數據來操作堆上的具體對象。reference數據只是一個指向對象的引用,具體的對象訪問根據不同虛擬機有不同的實現,主流的訪問方式有兩種:使用句柄直接指針

使用句柄:使⽤句柄訪問對象。即reference中存儲的是對象句柄的地址,⽽句柄中包含了對象實例數據

與類型數據的具體地址信息,相當於⼆級指針。

 

直接指針:直接指針,就是指reference中直接存儲對象的地址。但是Java堆對象的佈局中就必須考慮如何防止訪問類型數據相關信息。直接指針訪問對象。即reference中存儲的就是對象地址,相當於⼀級指針

對⽐

垃圾回收分析:⽅式 1(使用句柄)當垃圾回收移動對象時,reference中存儲的地址是穩定的地址,不需要修改,僅需要修改對象句柄的地址,所以當垃圾回收的時候就直接需要修改對象句柄的地址就可以了;⽅式2(直接指針)垃圾回收時需要修改reference中存儲的地址,在垃圾回收的時候要判斷實例數據是否存在,是否被垃圾回收過等做一系列判斷。所以說垃圾回收的效率⽅式2高於⽅式 1。

訪問效率分析,⽅式2優於⽅式1,因爲⽅式2只進⾏了⼀次指針定位,節省了時間開銷, ⽽這也是HotSpot採⽤的實現⽅式。

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