1. 程式人生 > >小師妹學JVM之:Dirty cards和PLAB

小師妹學JVM之:Dirty cards和PLAB

[toc] # 簡介 分代垃圾回收器在進行minor GC的時候會發生什麼操作呢?有沒有什麼提高效率的手段呢?今天我們和小師妹一起來了解一下垃圾回收中的Dirty cards和PLAB # 分代收集器中的空間劃分 小師妹:F師兄,能再講講分代垃圾收集器中的空間劃分嗎? 分代垃圾回收器中的Eden,Old和Survivor space幾個大家應該都很熟悉的分代技術。 Young Gen被劃分為1個Eden Space和2個Suvivor Space。當物件剛剛被建立的時候,是放在Eden space。 當Eden space滿的時候,就會觸發minor GC。會掃描Eden Space和一個Suvivor Space。如果在垃圾回收的時候發現Eden Space中的物件仍然有效,則會將其複製到另外一個Suvivor Space。 就這樣不斷的掃描,最後經過多次掃描發現仍然有效的物件會被放入Old Gen表示其生命週期比較長,可以減少垃圾回收時間。 ![](https://img-blog.csdnimg.cn/20200525214231730.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_0,text_aHR0cDovL3d3dy5mbHlkZWFuLmNvbQ==,size_35,color_8F8F8F,t_70) # Write barrier和Dirty cards 小師妹:F師兄,minor GC的時候,要將物件從Eden複製到Suvivor Space,從Suvivor Space中複製到Old space。GC是怎麼知道哪些物件是要被回收,哪些是不用被回收的呢? 小師妹,GC這裡用到了一項叫做Dirty cards的技術。 一般來說,新的物件是分配在Eden空間的。但是也有些物件是直接分配在Old space。 我們知道,GC的掃描是從一些根物件開始的,這些Root物件包括:正在執行的方法中的本地物件和輸入引數。活動的執行緒,載入類中的static欄位和JNI引用。 而這些根物件,一般都是儲存在old space中的。 通常來說old space的空間都會比較大。每次要要找到Eden和suvivor Space中哪些物件不再被引用,需要掃描整個old space肯定是不可取的。 所以JVM在這裡引入了Write barrier的技術。HotSpot中有兩種Write barrier,一種就是今天我們要講的Dirty cards,另外一種就是snapshot-at-the-beginning (SATB)。 SATB通常用在G1垃圾回收器中,這裡我們先不做深入的討論。 ![](https://img-blog.csdnimg.cn/20200607152228268.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_0,text_aHR0cDovL3d3dy5mbHlkZWFuLmNvbQ==,size_35,color_8F8F8F,t_70) 我們看下上圖中的Dirty cards的使用。 Dirty cards說起來很簡單,就是每當有程式對引用進行修改的時候,我們都會在一個Dirty cards的空間記錄一下被修改的memory page。 這樣在minor GC的時候,當引用的物件被修改了之後,我們會同步修改對應的Dirty cards。這樣每次掃描old space的時候,只需要選擇那些標記為Dirty cards的物件就可以了,避免了全域性掃描。 # PLAB 小師妹,F師兄,你講的好像很有道理的樣子,上次你講到我們在Eden空間分配物件的,為了提升分配的效率,使用了TLAB的計算。那麼在物件從Eden空間提升到Suvivor Space和old Space的時候有沒有同樣的技術呢? 當然有的,這個技術就叫做PLAB( promotion local allocation buffer)。每一個執行緒在survival space和old space中都一個PLAB。在提升的時候,可以避免多執行緒的競爭,從而提升效率。 我們可以使用-XX:+AlwaysTenure 將物件直接從Eden space提升到old space。 我們可以使用-XX:+PrintOldPLAB來輸出OldPLAB的資訊。 # old space分配物件 小師妹:F師兄,剛剛你講到新分配的物件可以直接在Old space,一般什麼物件可以這樣分配呢? 這個很好理解,如果你分配物件大小超過了Eden space的大小,是不是就只有old space可以分配物件了? 小師妹:對的,但是一般來說也不會使用這麼大的物件吧。 對的,我們可以通過設定-XX:PretenureSizeThreshold=n 來指定物件的大小,如果物件大小大於n,那麼就直接在old space分配。 > 注意,如果這個物件的大小比TLPB要小,那麼會首先在TLPB中分配。所以使用的時候要注意限制TLPB的大小。 # 總結 GC的執行是一個比較複雜的過程,大家可以細細體會。本文如果有什麼謬誤之處,歡迎微信我指正。謝謝大家。 > 本文作者:flydean程式那些事 > > 本文連結:[http://www.flydean.com/jvm-dirty-card-plab/](http://www.flydean.com/jvm-dirty-card-plab/) > > 本文來源:flydean的部落格 > > 歡迎關注我的公眾號:程式那些事,更多精彩等著您!