本篇文章給大家分享的是有關關于Java對象的創建有什么方法,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
虛擬機遇到一條new指令時,首先去檢查這個指令的參數是否能在方法區常量池中定位到一個類的符號引用,并檢查這個符號引用代表的類是否已被加載、解析和初始化過。如果沒有,就必須先執行相應的類加載過程。
類加載檢查過后,虛擬機為新生對象分配內存。對象所需內存大小在類加載過后就完全確定,為對象分配空間就等同于,從Java堆中劃分出一塊確定大小的內存。
此時有兩種情況:
如果Java堆中內存是規整的,那么虛擬機將會采用指針碰撞(BumpthePointer)分配內存。也就是用過的內存放在一邊,空閑的內存放另一邊,中間有個指針作為分界點指示器,那么分配內存就是把指針向空閑那一邊挪動了與對象相同大小的距離。
如果Java堆中內存不規整,已使用和未使用的內存相互交錯,那么虛擬機將會采用空閑列表(FreeList)分配內存。也就是虛擬機會維護一個空閑列表,記錄哪些內存塊可用,分配內存時就從空閑列表中找到一塊足夠大的空間分給對象實例,并更新列表。
選擇哪種分配方式由Java堆是否規整決定,而Java堆是否規整由垃圾收集器是否帶有壓縮整理功能決定。比如Serial、ParNew這種基于復制算法和標記-整理算法的收集器,就是采用指針碰撞法分配內存。而CMS這種基于標記-清除算法的收集器就是采用空閑列表。
還有一個問題就是要保證分配內存時的線程安全,即使是簡單的指針碰撞修改一下指針的位置,在并發情況下也不是線程安全的。解決這個問題有兩種方案,一種是對分配內存的動作進行同步處理,保證操作的原子性;另一種就是前面提到的本地線程分配緩沖TLAB。
在Java堆中內存分配完成后,虛擬機會將已分配的內存空間初始化為零值(不包括對象頭)。這保證了對象的實例字段在Java代碼中可以不用賦初始值就可以直接使用,程序能訪問到這些字段的數據類型所對應的零值。如果采用了TLAB,這一步也可以提前至TLAB分配時進行。
接下來對對象進行必要的設置,例如這個對象是哪個類的實例、如何找到類的元數據信息、對象的哈希碼、對象的GC分代年齡等信息,這些信息都存放在對象的對象頭(ObjectHeader)中。
這個時候,從虛擬機的角度看一個新的對象已經產生了,但從Java程序角度看對象的創建才剛開始,init方法還沒執行,所有的字段都還為零。所以這時會執行init的方法,把對象按照程序員的意愿初始化。
以上就是關于Java對象的創建有什么方法,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。