您好,登錄后才能下訂單哦!
源碼:
class T { int m = 8; } T t = new T();
匯編碼:
0 new #2 <T> 3 dup 4 invokespecial #3 <T.<init>> 7 astore_1 8 return
new #2
申請內存,在堆里面創(chuàng)建一個新對象。
半初始化,新建對象中的m值是0。
dup
復制操作,因為invokespecial會消耗一份引用,所以先復制一份
invokespecial
4 invokespecial #3 <T.>
init是調用它的構造方法。
此時對象中的m值是8。
astore_1
將符號和對象建立關聯(lián),即t和堆中的對象。
其實很簡單,今天看一個視頻說了半天。。。
知識點補充:java對象的創(chuàng)建過程
大家都知道,java使用new 關鍵字進行對象的創(chuàng)建,但這只是從語言層次上理解了對象的創(chuàng)建,下邊我們從jvm的角度來看看,對象是怎么被創(chuàng)建出來的,即對象的創(chuàng)建過程。
對象的創(chuàng)建大概分為以下幾步:
1:檢查類是否已經被加載;
2:為對象分配內存空間;
3:為對象字段設置零值;
4:設置對象頭;
5:執(zhí)行構造方法。
第一步,當程序遇到new 關鍵字時,首先會去運行時常量池中查找該引用所指向的類有沒有被虛擬機加載,如果沒有被加載,那么會進行類的加載過程,如果已經被加載,那么進行下一步,為對象分配內存空間;
第二步,加載完類之后,需要在堆內存中為該對象分配一定的空間,該空間的大小在類加載完成時就已經確定下來了,這里多說一點,為對象分配內存空間有兩種方式:
(1)第一種是jvm將堆區(qū)抽象為兩塊區(qū)域,一塊是已經被其他對象占用的區(qū)域,另一塊是空白區(qū)域,中間通過一個指針進行標注,這時只需要將指針向空白區(qū)域移動相應大小空間,就完成了內存的分配,當然這種劃分的方式要求虛擬機的對內存是地址連續(xù)的,且虛擬機帶有內存壓縮機制,可以在內存分配完成時壓縮內存,形成連續(xù)地址空間,這種分配內存方式成為“指針碰撞”,但是很明顯,這種方式也存在一個比較嚴重的問題,那就是多線程創(chuàng)建對象時,會導致指針劃分不一致的問題,例如A線程剛剛將指針移動到新位置,但是B線程之前讀取到的是指針之前的位置,這樣劃分內存時就出現不一致的問題,解決這種問題,虛擬機采用了循環(huán)CAS操作來保證內存的正確劃分;
(2)第二種也是為了解決第一種分配方式的不足而創(chuàng)建的方式,多線程分配內存時,虛擬機為每個線程分配了不同的空間,這樣每個線程在分配內存時只是在自己的空間中操作,從而避免了上述問題,不需要同步。當然,當線程自己的空間用完了才需要需申請空間,這時候需要進行同步鎖定。為每個線程分配的空間稱為“本地線程分配緩沖(TLAB)”,是否啟用TLAB需要通過 -XX:+/-UseTLAB參數來設定。
第三步,分配完內存后,需要對對象的字段進行零值初始化,對象頭除外,零值初始化意思就是對對象的字段賦0值,或者null值,這也就解釋了為什么這些字段在不需要進程初始化時候就能直接使用;
第四步,這里,虛擬機需要對這個將要創(chuàng)建出來的對象,進行信息標記,包括是否為新生代/老年代,對象的哈希碼,元數據信息,這些標記存放在對象頭信息中,對象頭非常復雜,這里不作解釋,可以另行百度;
第五步,也就是最后一步,執(zhí)行對象的構造方法,這里做的操作才是程序員真正想做的操作,例如初始化其他對象啊等等操作,至此,對象創(chuàng)建成功。
這里其實講的比較粗淺,只是對象創(chuàng)建的大概過程,例如對象頭、類的加載等等都是非常復雜的過程,我會在接下來解釋。
總結
到此這篇關于從匯編碼分析java對象的創(chuàng)建過程的文章就介紹到這了,更多相關從匯編碼分析java對象的創(chuàng)建過程內容請搜索億速云以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持億速云!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。