背景:我們在通過寫代碼創建一個對象時,有時會禿然想到,在創建一個對象時做了哪些事情?怎麼來的這個對象?那麼我們今天來了解一下創建對象的背後都發生了啥。在那之前:
一、對象創建過程
首先我們通過一張圖與一段代碼來大概瞭解創建一個對象的步驟。
- New類名 。》 圖中爲New String(),指定創建的對象爲String
- 根據new的參數在常景池中定位一個類符號的引用。》圖中創建了String對象,固會去找當前對象Class。
- 如果沒有找到這個符號的引用,說明類還沒有被加載,則進行類的加載,解析和初始化。》圖中爲加載當前對象Class。
- 虛擬機爲對象分配內存(位於堆中)。》爲當前String對象在堆中開闢空間。原理參考下文JVM如何爲對象開闢空間。
- 分配的內存初始化爲零值(不包括對象頭)。》如果是int那麼爲0,String則爲"",對值的初始化。
- 調用對象的<init>方法。》圖中爲執行String的構造方法
本次調用的String構造方法源碼:
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
創建過程原理示例代碼:
String str = new String("Hello World");
創建過程原理圖:
那麼經歷以上步驟,我們的String對象就創建完成了,是不是很簡單呢?
二、JVM如何爲對象開闢空間
首先使用哪種算法,跟垃圾回收機制有關。
標記整理和標記壓縮是指針碰撞的回收算法。指針回收會使用。
標記清除爲空間列表。 創建一般使用該算法。
當然垃圾回收機制影響算法的概念,相當於做了垃圾分類的城市,你在處理垃圾的時候就要把垃圾分類再丟,如果沒有做垃圾分類的城市,那麼你可以直接全部丟一個袋子扔掉。這時候就是不同城市的垃圾回收機制影響你的處理垃圾的思想分類行爲,同理就是垃圾回收機制影響程序的算法原理。
2.1、指針碰撞
首先Cas實現同步是在CPU層面加鎖。硬件層面加鎖。效率高。
原理實際上會在放入的時候調用C語言的CAS方法。Unsafe類中的compareAndSwapObject方法
這裏案例的意思就是內存被obj1和obj2佔用後,剩下的空間只能存放一個對象,那麼如果此時多線程創建obj3和obj4,同時去搶,那麼總有一個資源會搶到。當然如果說非得創建兩個就會出現內存溢出的問題。
內存溢出參考:https://blog.csdn.net/qq_43227967/article/details/106054100
2.2、空閒列表
空閒列表存放的原則:哪塊區域空閒,就會存放在哪塊區域
當然如果是多線程,那麼其實是有一個線程緩存區的概念,會有一塊一塊的區域,每一個線程對應一塊區域,如果A線程滿了,那麼就會通過CAS機制去搶佔線程B的區域。來避免同時搶佔一個位置的情況。
三、總結
Java創建對象首先是new 類名,那麼實現會根據new的參數在常量池中定義一個對該類符號的引用,如果沒有找到這個符號的引用,說明這個類沒有被加載,那麼進行類的加載、解析、初始化。然後虛擬機爲其分配內存(位於堆中)使用指針碰撞或者是空閒列表,與垃圾算法相關聯,默認初始值爲零。最後調用對象的init方法。完成創建。