简介
分代垃圾回收器在进行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示意其生命周期比拟长,能够缩小垃圾回收工夫。
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垃圾回收器中,这里咱们先不做深刻的探讨。
咱们看下上图中的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/
本文起源:flydean的博客
欢送关注我的公众号:程序那些事,更多精彩等着您!