摘要:知道三色标记吗?是红黄蓝三色标记吗?
本文分享自华为云社区《从三色标记说开去》,原文做者:java初中生。java
【1】关于三色标记
前几天,公司临时派我去面试一个java实习生,因为没有这方面的任何经验,因而一不当心,我就问超纲了。面试
问过了java基础,我随口又问了一句,知道三色标记吗?算法
他显然是懵逼了一瞬间,但也仅仅一瞬间,而后振振有词地反问,是红黄蓝三色标记吗?数组
这却是反把我问住了。安全
面试有问题答不出来,这其实能够理解,不懂就说不懂,不会就说不会,子曾经曰过,知之为知之。并发
三色标记,正经来讲,就只有黑白灰三个颜色。url
但实际上,三色标记,和颜色其实没有任何关系,只与一次扫描状态相关。spa
- 黑色节点,表明根节点或者已扫描完的节点,该节点的子节点也被扫描完;
- 灰色节点,表明已扫描完的节点,该节点的子节点存在未被扫描的状况;
- 白色节点,表明未被扫描的节点。
上图中,A就是黑色节点,B为灰色,由于B的子节点C未被扫描,C则是白色节点。.net
若是,扫描结束,C依旧是白色,则C被回收。线程
但这里会存在一个问题,若是在上图的状况下,BC的引用断掉,而AC的引用被创建,以下图:
则会出现如下状况:
- B扫描完,无引用,变黑。
- C,按道理说,也会变灰,而后变黑。
- 但A此时已是黑色节点,则不会扫描其引用,因此C不会被扫描,仍是白色。
- 最后,C会被当垃圾回收。
这显然是一个误操做,由于C当前是根可达的,那该问题怎么办呢?
经常使用的垃圾回收器,CMS和G1都给出了解决方案。
CMS的方法叫作Incremental Update算法。
该算法从结果入手,判断扫描完结时,是否有白色对象被黑色对象引用,若是被引用,则经过write barrier写屏障技术,把黑色的对象从新标记为灰色,而后从新扫描。
G1的方法叫作SATB算法。
该算法从源头入手,GC开始以前拍摄快照,设定全部存在引用的对象,都是存活的。
GC扫描以后,再次拍摄快照,将新引用的存活对象标记。
而后将快照叠加。
这样,C显示的是被A,B两个对象引用。
但这样会有一个弊端,若是此时,AC之间的引用没有被创建,则C原本应该被回收,但此轮却并无被回收。
【2】跨代引用的问题
跨代引用这个概念被提出来的时候,不少人都有似曾相识的感受。但具体要说,不少人就说不出因此然来了。
其实,java堆说到底就两个代(年轻代和老年代),持久代在jdk的某个版本后,就被放到本地方法栈了。
跨代引用,即父节点在一个代,而引用对象在另外一个代。
通常来讲,父节点都在老年代,引用对象在年轻代。
如上图,X引用和Y引用都是属于跨代引用。
跨代引用通常多发生在G1回收器中,由于G1的内存采用分块的模式,内存区域不稳定。
那么,年轻代回收(young GC)时,是否要根据可达性分析,遍历全部的老年代关联,直到根节点呢。
不须要。
只要父节点在老年代,则一概视为根节点。
在这里(跨代引用)要引入两个概念,结果集和卡表。卡表能够看做一个老年代分区的集合或者数组,以下图。
结果集,就是一组相似于map的容器,key存放卡表的下标,value存放引用关系
想一想这样作的好处是什么?
【3】安全点和安全区域
java工做线程和垃圾回收线程,通常状况下,是不能同时进行的。
一般老师讲到这个问题的时候,会打个比方:吃饭和洗碗擦桌子。
之因此工做线程和垃圾回收线程不能同时进行,是由于人不能一边吃饭一边收拾碗筷(触手怪除外)。
同理,还有一个问题,你也不能把饭吃到一半,把碗拿过去洗。
因此,你必须在吃完饭的时候,洗碗。
吃完饭的这个时间,就是安全点。
通常来讲,安全点是某个线程的结束或者中断的时间,能够是方法调用,循环跳转,异常跳转等。
再回头说说垃圾回收的全过程。
- 业务线程执行过程当中,会不断轮询一个标志位,该标志位处于垃圾回收线程中;
- 若是须要作垃圾回收,回收线程会将标志位改掉;
- 业务线程收到标志位信息,会走到安全点,而后中止;
- 垃圾回收线程启动,回收垃圾。
那么,安全区域是什么呢?
一个区域全部的点都是安全点,这一部分就是安全区域。
仍是拿原来那个例子,若是你晚上减肥,不想吃饭,碗什么的,随时均可以洗。
【4】如何查看GC日志
直接上命令:-XX+PrintGCDetails。
该命令能够在控制台打印GC日志。
日志内容以下:
【5】终:垃圾回收各指标
吞吐量:指在应用程序的生命周期内,应用程序所花费的时间和系统总运行时间的比值。
公式:吞吐量=系统应用时间/系统总运行时间
垃圾回收器负载:和吞吐量正好相反,垃圾回收器负载指垃圾回收器耗时与系统运行总时间的比值。
公式:吞吐量=垃圾回收时间/系统总运行时间
停顿时间(延迟):指垃圾回收器正在运行时,应用程序的暂停时间。
PS:独占回收器延迟长,但吞吐量高,并发回收器,延迟少,但吞吐量低。
垃圾回收频率:指垃圾回收器多长时间会运行一次。
PS:垃圾回收器的频率应该是越低越好。
反应时间:指当一个对象被称为垃圾后多长时间内,它所占据的内存空间会被释放。
PS:即垃圾回收的周期
over~~
堆分配:不一样的垃圾回收器对堆内存的分配方式多是不一样的。一个良好的垃圾收集器应该有一个合理的堆内存区间划分。
本文参考资料:https://blog.csdn.net/xingkongjuhao/article/details/101801460