JVM基础知识---对象的创建过程
生活随笔
收集整理的這篇文章主要介紹了
JVM基础知识---对象的创建过程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
對象的創建過程
- 一. 對象的創建過程
- ①. 類加載檢查
- ②.分配內存
- ③. 初始化零值
- ④. 設置對象頭
- ⑤. 執行init方法
- 二. 對象的內存布局
- ①. 對象頭
- ②. 實例數據
- ③. 對齊填充
- 三. 對象的訪問定位
- ①. 使用句柄訪問對象
- ②. 使用直接指針訪問對象
一. 對象的創建過程
①. 類加載檢查
- 虛擬機遇到一條 new 指令時,首先將去檢查這個指令的參數是否能在常量池中定位到這個類的符號引用,并且檢查這個符號引用代表的類是否已被加載過、解析和初始化過。如果沒有,那必須先執行相應的類加載過程。
- 上一篇博客類的加載全過程分析
②.分配內存
- 在類加載檢查通過后,接下來虛擬機將為新生對象分配內存。對象所需的內存大小在類加載完成后便可確定,為對象分配空間的任務等同于把一塊確定大小的內存從 Java 堆中劃分出來。
分配方式有 指針碰撞 和 空閑列表 兩種
- 指針碰撞:如果jvm的垃圾收集器采用復制算法或標記-整理算法,那么堆中空閑內存是完整的區域,并且空閑內存和已使用內存之間由一個指針標記。那么當為一個對象分配內存時,只需移動指針即可(指針向空間那邊挪動一段與對象大小相等的距離)。
- 空閑列表: 如果jvm的垃圾收集器采用標記-清除算法,那么堆中空閑區域交錯,因此,虛擬機需要維護一個列表記錄上哪些內存塊是可用的,在分配的時候從列表中找到一塊足夠大的空間劃分給對象實例,并更新列表上的記錄。
由于JVM創建對象的行為非常頻繁,因此需要考慮內存分配的并發問題解決方案:
③. 初始化零值
- 內存分配完成后,虛擬機需要將分配到的內存空間都初始化為零值(不包括對象頭),這一步操作保證了對象的實例字段在 Java 代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數據類型所對應的零值。
④. 設置對象頭
- 初始化零值完成之后,虛擬機要對對象進行必要的設置
⑤. 執行init方法
- 在上面工作都完成之后,從虛擬機的視角來看,一個新的對象已經產生了,但從 Java 程序的視角來看,對象創建才剛開始,<init> 方法還沒有執行,所有的字段都還為零。所以一般來說,執行 new 指令之后會接著執行<init> 方法,把對象按照程序員的意愿進行初始化,這樣一個真正可用的對象才算完全產生出來。
二. 對象的內存布局
- 在 Hotspot 虛擬機中,對象在內存中的布局可以分為 3 塊區域:對象頭、實例數據和對齊填充。
①. 對象頭
對象頭:兩部分數據構成
②. 實例數據
實例數據:
- 對象真正存儲的有效信息,也是在程序代碼中定義的各類型的字段內容。它就是成員變量的值,其中包含父類的成員變量和本類的成員變量。
③. 對齊填充
對齊填充:不是必需存在的,為了字節填充,僅起到占位符的作用。
- 僅僅起著占位符的作用,由于HotSpot要求對象的總長度必須是8字節的整數倍。由于對象頭一定是8字節的整數倍,但實例數據部分的長度是任意的,因此需要對齊填充字段來補全,確保整個對象的長度為8的整數倍。
三. 對象的訪問定位
- 建立對象就是為了使用對象,我們的 Java 程序通過棧上的 reference 數據來操作堆上的具體對象。
- 訪問方式有 使用句柄和 直接指針兩種
①. 使用句柄訪問對象
- 如果使用句柄的話,那么 Java 堆中將會劃分出一塊內存來作為句柄池,reference 中存儲的就是對象的句柄地址,而句柄中包含了對象實例數據與類型數據各自的具體地址信息;
②. 使用直接指針訪問對象
- 直接指針: 如果使用直接指針訪問,reference 中存儲的直接就是對象的地址。
總結
以上是生活随笔為你收集整理的JVM基础知识---对象的创建过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 寿命相关数据集
- 下一篇: Jenkins内存占用过高的问题