小师妹学JVM之:Dirty cards和PLAB

简介

分代垃圾回收器在进行minor GC的时候会发生什么操做呢?有没有什么提升效率的手段呢?今天咱们和小师妹一块儿来了解一下垃圾回收中的Dirty cards和PLAB微信

分代收集器中的空间划分

小师妹:F师兄,能再讲讲分代垃圾收集器中的空间划分吗?多线程

分代垃圾回收器中的Eden,Old和Survivor space几个你们应该都很熟悉的分代技术。jvm

Young Gen被划分为1个Eden Space和2个Suvivor Space。当对象刚刚被建立的时候,是放在Eden space。spa

当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是怎么知道哪些对象是要被回收,哪些是不用被回收的呢?blog

小师妹,GC这里用到了一项叫作Dirty cards的技术。生命周期

通常来讲,新的对象是分配在Eden空间的。可是也有些对象是直接分配在Old space。rem

咱们知道,GC的扫描是从一些根对象开始的,这些Root对象包括:正在执行的方法中的本地对象和输入参数。活动的线程,加载类中的static字段和JNI引用。get

而这些根对象,通常都是存储在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的博客

欢迎关注个人公众号:程序那些事,更多精彩等着您!

相关文章
相关标签/搜索