一、內存分配。
這部分我們說一下對象在 java 堆中是如何分配、布局、訪問以及內存分配的原則。
1、對象的創建。
我們用 new 來創建對象,來看看系統運行到 new 時,虛擬機在干什么。此時的類就像一塊肉,他要經過層層安檢,才能到達人類的飯桌。
(1)查看在常量池中是否有對應的符號引用。【在方法區中進行】
(2)查看此類是否被加載、解析和初始化過。【在方法區中進行】
(3)領取新生對象的內存。有兩種方式:指針碰撞和空間列表。【在堆中進行】
(4)將分配到的內存空間初始化為零。
(5)對對象進行必要的設置,比如其實哪個類的實例,對象的哈希碼之類的。這些信息存放在對象的對象頭中。
(6)如果 java 代碼對對象進行了賦值,則會走到第六步,執行
方法。此方法的作用就是對對象進行初始化。
2、對象的內存布局。
對象在內存中的存儲布局分為三個部分:對象頭 + 實例數據 + 對其補充
- 對象頭。
對象頭里面有兩部分信息:
(1)運行時數據,包括哈希碼、GC 分代年齡、鎖狀態標志等。
(2)類型指針,虛擬機通過這個指針來確定這個對象是哪個類的實例。
- 實例數據。
實例數據中存放的是代碼中定義的各種類型的字段內容。
- 對其填充。
對齊填充起的是占位符的作用,不是必然存在的,其只要保證對象的大小是 8 字節的整數倍即可。
3、對象的訪問定位。
建立完對象后,我們就可以使用對象了。通過句柄和直接指針兩種方式。
- 句柄。
句柄訪問就是在 java 堆中劃分出一塊內存區域作為句柄池,句柄中包含了實例數據和類型數據各自具體的地址信息。
- 直接指針。
直接指針之所以 “直接”,是因為它去除了句柄這個中介。所以在速度上比句柄快。
在 HotSpot 虛擬機中,使用的是這種方式。
說完了對象在 java 堆中是如何分配,布局和訪問的,接下來我們說說內存分配的原則。
4、內存分配的原則。
堆大致分為新生代,老年代,永久代。對象的內存分配主要分配在新生代的 Eden 區,少數情況下會直接分配到老年代中。分配的規則不是 100% 固定的,取決于垃圾收集器組合和參數設置等。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.