以Object obj = new Object();的過程進行分析這一行代碼的背後,JVM都做了些什麼。
一、檢查常量池中是否存在該類的符號引用,如果沒有,則先載入該類,並解析和初始化
二、為對象分配記憶體
記憶體大小在類載入的時候已經確定大小,如下圖:
分配記憶體過程中需要考慮的問題:
2.1記憶體是否規整
① 假設Java 堆中記憶體是連續規整的,也就是說Heap中一側是已經使用過的記憶體空間,而另一側是空閑空間,則此時使用指標指向起始空閑記憶體,當需要分配新的空間時,只需要將指標向後移動制定空間大小位置即可完成記憶體的分配,這種分配方式稱為“指標碰撞”(Bump the Pointer)
② 假設記憶體並不是連續規整的,空閑和使用的相互交錯,則此時JVM就需要記錄哪些記憶體塊石可用的,分配時,分配足夠大的空間給對象執行個體,同事更新記錄列表。這種方式稱為“空閑列表”(Free List)
而是採用Bump the Pointer的方式還是Free List的方式由JVM Heap是否規整決定,而Heap的規整與否又由所採用的垃圾收集器是否帶有亞索整理的功能決定。使用Serial、ParNew等帶有Compact過程的收集器時則採用指標碰撞,而使用CMS這種給予Mark Sweep演算法收集器時,採用Free List方式。
2.2對象的建立十分頻繁,如何解決並髮帶來的不安全問題
方法一、同步,即對分配記憶體空間的動作進行同步處理——-採用CAS加上失敗重試的方式保證更新操作的原子性。
方法二、TLAB,把記憶體配置的動作按照線程劃分在不同的空間上進行,即每個線程預先分配一小塊記憶體,這種方式稱為本地線程分配緩衝(Thread Local Allocation Buffer),這種方式只需要在分配新的TLAB時進行同步鎖定
是否採用TLAB方式可以通過使用-XX:+/-UserTLAB決定 三、記憶體配置完成後的必要設定
如: 該執行個體為那一個類的執行個體 類的中繼資料資訊 對象的雜湊碼 對象的GC分代資訊 等等
以上資訊位於對象的頭資訊中(Object Header),除此之外,對象的其他欄位都還是0,至此一個新的對象已經產生,但是尚未進行初始化。 四、對象的初始化,執行init方法
至此,一個對象完成建立過程