Java對象建立

java對象的建立過程java

  • jvm遇到new指令,回去檢查這個指令的參數是否能在常量池中定位到一個類的符號引用,而且在檢查這個符號引用表明的類是否已經被加載、解析和初始化過。若是沒有就執行類加載過程。
  • 爲對象分配空間,把一塊固定大小的內存從java堆裏劃分出來。若是java堆時那種整齊的,一邊放已經用過的內存,一邊放沒有用過的內存,這樣就有一箇中間指針隔開兩個區域,只要把這個指針移到相應位置便可,這種方法叫指針碰撞。若是已經使用內存和未使用的內存交錯,就須要一個空閒列表方法來決定分配在哪裏。
  • 多線程併發時會出現正在給對象A分配內存,還沒來得急修改指針,對象B又用這個指針分配內存,這就出現問題了,兩種解決方法:
    • 對分配的內存空間的動做進行同步
    • 把內存分配動做按照線程劃分在不一樣的空間之中進行。
  • 內存分配完以後jvm將分配到的內存全都初始化爲零。接下來設置對象頭,包括這個對象是哪一個類的實例,如何才能找到該類的原數據信息,對象的哈希碼,對象的GC分代年齡等信息。
  • 執行init,初始化。

對象的內存佈局數據結構

  • 對象頭:一部分是存儲對象自身的運行時數據,如哈希碼,GC分代年齡等。另外一部分時類型指針,即對象指向類原數據的指針。
  • 實例數據
  • 對齊填充

五種狀況必須初始化多線程

  • 遇到new,getstatic, putstatic,invokestatic這4條字節碼的時候,若是類沒有進行初始化,則須要先觸發其初始化。
  • 使用java.lang.reflect包方法的對類進行反射調用的時候
  • 初始化一個類,他的父類還沒初始化,則先觸發父類的初始化
  • 當虛擬機啓動時,用戶須要指定一個執行主類,虛擬機會先初始化這個類
  • 當使用JDK1.7時動態語言支持的時候,一個java.lang.invoke.MethodHandle實例最後解析結果爲REF_getstatic,REF_pustatic,REF_invokeStatic的方法句柄,而且這個方法句柄所對應的類沒有進行初始化,則須要先觸發其初始化。

加載階段,jvm須要完成如下併發

  • 經過一個類的全限定名來獲取定義此類的二進制字節流。
  • 將定義類的二進制字節流所表明的靜態存儲結構轉換爲方法區的運行時數據結構
  • 在java堆中生成一個表明該類的java.lang.Class對象,做爲方法區數據的訪問入口。
相關文章
相關標籤/搜索