JVM(四)-虛擬機對象

概述:

  上一篇文章,介紹了虛擬機類加載的過程,那麼類加載好以後,虛擬機下一步該幹什麼呢。咱們知道java是面向對象的編程語言,因此對象能夠說是java'的靈魂,這篇文章咱們就來介紹java

虛擬機是如何建立對象、對象內存分配以及對象是如何使用的(訪問定位)。因爲各個虛擬機的實現不盡相同,因此這裏咱們以最經常使用的HotSpot虛擬機爲例來介紹。編程

對象的建立:

  對象在虛擬機中建立的步驟以下:數組

  1. 當虛擬機遇到一條字節碼new指令時,首先會去檢查這個類是否被加載、解析和初始化,若是沒有,則執行類加載(類加載步驟這裏就不介紹了,請查看JVM(三))。
  2. 類加載檢查經過後,接下來虛擬機將在堆中爲新生對象分配和對象同等大小的內存。
  3. 內存分配完以後,虛擬機會將分配到的內存空間(不包括對象頭)都初始化爲零值,保證了對象的實例字段有初始值,使得不賦值也可使用,只是值爲零而已(注意,若是是引用對象則爲null)。
  4. 接下來,java虛擬機還要對對象進行必要的設置,好比這個對象是哪一個類的實例、如何才能找到類的元數據信息、對象的哈希碼、對象的GC分代年齡等信息。
  5. 執行Class文件中<init>()方法,即構造函數,這樣一個真正可用的對象纔算徹底構建完成。

對象的內存佈局:

  在HotSpot虛擬機裏,對象在堆內存中的存儲佈局能夠劃分爲三個部分:對象頭、實例數據和對其填充。編程語言

對象頭:

  HotSpot虛擬機對象的對象頭部分包括兩類信息:函數

  1. 第一類是用於存儲對象自身的運行數據,如何哈希碼(hashcode)、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等,官方稱它爲"Mark Word"。
  2. 對象頭的另一部分是類型指針,即對象指向它的類型元數據指針,java虛擬機經過指針來肯定該對象是哪一個類型的實例。若是是數組對象,在對象頭中還有一塊用於記錄數組長度的數據。

實例數據:

  顧名思義,實例數據部分存儲的就是實例對象的相關信息了,即咱們在程序代碼裏面所定義的各類類型的字段內容,不管是從父類繼承下來的,仍是在子類中定義的字段都必須記錄起來。佈局

對齊填充:

  對象的第三部分是對齊填充,這並非必然存在的,也沒有特別的含義,它僅僅起着佔位符的做用。因爲HotSpot虛擬機的自動內存管理系統要求對象的起始地址必須是8字節的整數倍,因此線程

不足8的整數倍就須要補齊。指針

對象的訪問定位:

  建立對象天然是爲了後續使用該對象,java虛擬機規範規定java程序經過虛擬機棧的reference來操做堆上的具體對象,各個虛擬機實現的訪問方式也不盡相同,主流的訪問方式主要使用句柄和直接指針兩種,code

咱們先來看經過句柄的方式訪問,以下圖:對象

 

 

  經過句柄訪問,java堆中會將劃分出一塊內存來做句柄池,reference中存儲的就是對象的句柄地址,句柄中包含了對象實例數據以及類型數據的地址信息。而指針訪問的話,

reference中存儲的直接就是對象地址,對象實例中同時還須要存指向對象類型數據的指針。以下圖所示:

 

   這兩種對象訪問方法各有優點,直接指針訪問方式,雖然訪問訪問速度快,可是垃圾回收的效率沒有句柄池的效率高。咱們經常使用的HotSpot是使用的直接指針的方式訪問對象。

相關文章
相關標籤/搜索