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