JVM:堆中对象的创建?定位?可达性?
對象的創(chuàng)建
指針碰撞:若是堆中的內(nèi)存是絕對規(guī)整的,所有用過的內(nèi)存放在一邊,空閑的放在另一邊,中間放著一個指針作為分界點(diǎn)的指示器,那所分配內(nèi)存就僅僅是把那個指針向空閑空間那邊挪動一段與對象大小相等的距離。
指針碰撞要求堆中所采用的GC搜集器是帶有“壓縮整理”功能的!
空閑列表:與指針碰撞相反,堆的內(nèi)存空間是無序的,已使用內(nèi)存和空閑內(nèi)存交錯,那便要使用一個空閑列表來記錄堆中空閑內(nèi)存的情況!根據(jù)空閑列表來分配空閑內(nèi)存。
當(dāng)對象訪問十分頻繁,且在多線程并發(fā)情況下,還要考慮內(nèi)存指針的同步問題!?
兩種方案:一種是基于CAS的同步方式保證操作原子性;另一種是TLAB(本地線程緩沖區(qū)),也即是提前在堆中為每個線程劃分一小塊內(nèi)存,這樣一來后來內(nèi)存的分配可按照各線程在不同的TLAB中進(jìn)行,起到隔離作用!
對象的定位
Pojo a = new Pojo();
a引用作為局部變量存在棧中,Pojo實(shí)例對象存在堆中,Pojo類型數(shù)據(jù)存在方法區(qū)。
a如何定位到堆中的對象呢?
1)句柄
2)直接指針
?
所謂句柄就是,在堆中維護(hù)一個句柄池,a引用指向句柄池中的某一個句柄,而這個句柄里面存著一個堆中對象實(shí)例的地址和一個方法區(qū)中類信息的地址。
所謂直接指針就是,a引用直接指向堆中的實(shí)例對象數(shù)據(jù),在這個實(shí)例對象中存在一個指向方法區(qū)的類信息的指針。
使用句柄最大好處就是引用中存儲的是穩(wěn)定的句柄地址,在對象被移動時(shí)(例如GC),只會改變句柄中的實(shí)例對象的指針,而棧中的引用不需改變。
使用直接指針最大好處就是速度比較快,節(jié)省了一次指針定位的時(shí)間,適用于java對象訪問頻繁的場景。
可達(dá)性
可達(dá)性算法的基本思想是:通過一系列稱為GCRoots的對象作為根節(jié)點(diǎn),向下開始搜索,搜索所走過的路徑成為引用鏈,當(dāng)一個對象到GCRoots沒有任何引用鏈相連的話,則證明該對象是不可用的,即為垃圾對象!
但是但是但是!!!!垃圾對象就一定是垃圾對象嗎?不一定,垃圾對象可能會在finalize()結(jié)束之前復(fù)活!!!成為新的可用對象!!但是如果finalize()方法執(zhí)行完之后,那么不可用對象就會都被回收!!!
finalize()方法只會被調(diào)用一次
分析:第一次gc時(shí)調(diào)用finalize()時(shí),由于將this賦值給obj,導(dǎo)致obj重新獲得引用,逃逸出F-QUEUE隊(duì)列,成功拯救自己!
但是當(dāng)?shù)诙蜧C的時(shí)候,由于finalize()方法只會被調(diào)用一次,所以obj會被回收掉!!!
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的JVM:堆中对象的创建?定位?可达性?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM:JVM内存划分、主内存、工作内存
- 下一篇: JVM:-Xmx和-Xms应该维持什么样