對象創建:
1、Java語言層面:new關鍵字
2、
1)虛擬機遇到一條new指令
2)能否在常量池中定位到該符號引用,並且判斷是否已被加載,解析和初始化過,如果已經加載解析初始化就進入第4),否則進入3)
3)執行類的加載過程
4)類加載檢查完成後,虛擬機爲新生對象分配內存,對象所需內存空間的大小在類加載完成後便可完全確定,分配的過程等同於將一塊確定大小的內存從java對中劃分出來。
i)對內存分配方法
ii)如果堆內存是規整的,“指針碰撞”,所有用過的內存放到一邊,空閒的內存放到另外一邊,中間放着一個指針作爲分界點的指示器,分配內存就是僅僅把指針項空閒的一邊挪動於對象大小相等的距離
iii)如果不規整,需要維護一個列表,表明哪些內存時可用的。“空閒列表”
j)對象的創建愛你是一個頻繁的操作,正在給對象A分配內存,對象B有同事使用原來的指針來分配內存
jj)對分配內存空間的動作進行同步處理,虛擬機採用cas配上失敗充實的方式保證更新操作的原子性
jjj)吧內存分配動作按照線程不同劃分到不同的空間之中,每個線程在java堆中預先分配一小塊內存,成爲本地線程分配緩衝
內存分配完成,將分配到的內存控件初始化爲0,進行必要的設置,該對象的各種信息,初始化
對象內存佈局
對象在內存中存儲的佈局可以分爲3塊區域:對象頭,示例數據,對齊填充
對象頭:
1)存儲對象自身的運行時數據:如哈希碼,gc分帶年齡,鎖狀態標識,線程持有的所,偏向線程ID,偏向時間戳,mark word64bit
2)類型指針:對象指向它類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個累的實例,並不是所有的虛擬機的實現都必須在對象數據保留類型指針,超找對象元數據信息並不一定要經過底下那個本身,如果對象是一個java數組,需要在對象頭中有一塊用於記錄數組長度的數據。
實例數據:
對象真正存儲的有效信息,程序代碼中所定義額各種類型字段內容,是真正有意義的數據。
對齊填充:沒有特別的含義,僅僅起到佔位符的作用
對象的訪問定位,通過棧上面的對象引用訪問堆上的具體的數據
垃圾回收的時候,引用存儲的是指針信息,很穩定,垃圾回收移動對象只改變句柄中示例數據的指針,引用本身不需要改變
速度快,節省指針定位開銷
JAVA內存溢出來源,不斷創建對象會導致對內存溢出
虛擬機棧和本地方法棧溢出(遞歸)
方法區和運行時常量池溢出
本機直接內存溢出