关于java:三色标记原理我给应聘者问懵了

39次阅读

共计 2130 个字符,预计需要花费 6 分钟才能阅读完成。

摘要:晓得三色标记吗?是红黄蓝三色标记吗?

本文分享自华为云社区《从三色标记说开去》,原文作者:java 初中生。

【1】对于三色标记

前几天,公司长期派我去面试一个 java 实习生,因为没有这方面的任何教训,于是一不小心,我就问超纲了。

问过了 java 根底,我随口又问了一句,晓得三色标记吗?

他显然是懵逼了一瞬间,但也仅仅一瞬间,而后振振有词地反诘,是红黄蓝三色标记吗?

这倒是反把我问住了。

面试有问题答不进去,这其实能够了解,不懂就说不懂,不会就说不会,子已经曰过,知之为知之。

三色标记,正经来说,就只有黑白灰三个色彩。

但实际上,三色标记,和色彩其实没有任何关系,只与一次扫描状态相干。

  • 彩色节点,代表根节点或者已扫描完的节点,该节点的子节点也被扫描完;
  • 灰色节点,代表已扫描完的节点,该节点的子节点存在未被扫描的状况;
  • 红色节点,代表未被扫描的节点。

    上图中,A 就是彩色节点,B 为灰色,因为 B 的子节点 C 未被扫描,C 则是红色节点。

如果,扫描完结,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/xingkon…

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0