Java虛擬機是怎麼new的對象?

本文涉及:Java中的new命令以後發生的事java

類加載檢查

java虛擬機在遇到一條 new 指令時,首先會檢查是否能在常量池中定位到這個類的符號引用,而且是否已被加載過、解析和初始化過。若是沒有,那必須先執行類加載過程面試

類加載的相關知識可參考:JVM的類加載機制redis

分配內存

在類加載檢查經過後,接下來虛擬機將爲新生對象分配內存。算法

分配方式有 指針碰撞 和 空閒列表 兩種bash

  • 指針碰撞:Java堆中的內存是規整的,全部用過的內存都放在一邊,空閒的內存放在另外一邊,中間放着一個指針做爲分界點的指示器,分配內存也就是把指針向空閒空間那邊移動一段與內存大小相等的距離。多線程

  • 空閒列表:Java堆中的內存不是規整的,已使用的內存和空閒的內存相互交錯,就沒有辦法簡單的進行指針碰撞了。虛擬機必須維護一張列表,記錄哪些內存塊是可用的,在分配的時候從列表中找到一塊足夠大的空間劃分給對象實例,並更新列表上的記錄併發

Java 堆內存是否規整,取決於 GC 的垃圾回收算法,在JVM中標記壓縮、複製算法的內存是規整的、而標記清除則是不規整的源碼分析

垃圾回收算法相關知識可參考:JVM垃圾收集算法詳解學習

內存分配併發問題
  • CAS操做:CAS是屬於原子性操做,更多關於此內容可參考此內容:Java原子類操做原理剖析spa

  • TLAB: 爲每個線程預先在Eden區分配一起內存,JVM在給線程中的對象分配內存時,首先在TLAB分配,當對象大於TLAB中的剩餘內存或TLAB的內存已用盡時,再採用上述的CAS進行內存分配

內存空間初始化

內存分配完成後,虛擬機須要將分配到的內存空間都初始化爲零值。這一步操做保證了對象的實例字段在 Java 代碼中能夠不賦初始值就直接使用,程序能訪問到這些字段的數據類型所對應的零值。例如:

int a=1
long b=2
實際上在這時被賦值爲了
a=0
b=0L複製代碼
設置對象頭

內存空間初始化完成以後,虛擬機要在對象頭中保存如下必要的信息:

  • 這個對象是那個類的實例

  • 如何才能找到類的元數據信息

  • 對象的哈希碼

  • 對象的 GC 分代年齡

  • 等等

執行構造方法

這裏纔是咱們最熟悉的地方

推薦閱讀

  1. SpringCloud學習系列彙總
  2. 爲何一線大廠面試必問redis,有啥好問的?
  3. 多線程面試必備基礎知識彙總
  4. Java集合源碼分析彙總-JDK1.8
  5. Linux經常使用命令速查-彙總篇

博客全部文章首發於公衆號《Java學習錄》轉載請保留 掃碼關注公衆號便可領取2000GJava學習資源

1

相關文章
相關標籤/搜索