diff --git a/jvm/深入理解java虚拟机.md b/jvm/深入理解java虚拟机.md index 613eda7..7186ba1 100644 --- a/jvm/深入理解java虚拟机.md +++ b/jvm/深入理解java虚拟机.md @@ -34,6 +34,9 @@ - [基于复制算法的虚拟机新生代内存划分](#基于复制算法的虚拟机新生代内存划分) - [标记-整理算法](#标记-整理算法) - [分代收集算法](#分代收集算法) + - [三色标记算法](#三色标记算法) + - [三色标记算法在并发标记时的缺陷](#三色标记算法在并发标记时的缺陷) + - [CMS对该问题的解决方法](#cms对该问题的解决方法) - [Hotspot算法实现](#hotspot算法实现) - [枚举根节点](#枚举根节点) - [OopMap](#oopmap) @@ -308,6 +311,23 @@ Java虚拟机规范并不强制要求对方法区进行垃圾回收,并且在 - 在新生代,存活对象较少,复制的目标区的内存占比也可以划分的更少,并且较少存活对象带来的复制成本也较低 - 在老年代,对象存活率更高,并且没有额外的内存空间来对齐进行担保,故而不应使用复制算法,而是应当采用`标记-清除`算法或`标记-整理`算法来进行回收 +#### 三色标记算法 +为了减少垃圾回收过程对于用户线程的阻塞,引入了三色标记算法。三色标记算法在标记垃圾的过程中将对象分为了三种不同的状态: +- 黑:黑色代表该对象及其所有引用已经被完全扫描,被标记为黑色代表该对象不会再次被扫描 +- 白:白色代表该对象从未被扫描,如果标记过程结束后,仍然处于白色状态的对象将会被视为垃圾 +- 灰:灰色代表该对象已经扫描过但是没有完全扫描,未来还会对该对象进行扫描 + +##### 三色标记算法在并发标记时的缺陷 +如果在采用三色标记算法的同时并发的执行用户线程,用户线程在可达性分析过程中对对象进行标记时,仍然能改变对象之间的引用关系,那么可能会出现如下问题: +- 浮动垃圾(多标):假如一个对象已经被标记为黑色/灰色、可达,但是用户线程后续断开了其他对象到该对象的引用,该对象实际应当被回收,但是本次仍然会存活,得等待到下一阶段再次回收 +- 对象消失(漏标):除此之外,还会出现对象消失的问题,假设用户线程新增了黑色对象到白色对象的引用,那么黑色对象不会再被重新扫描,此时白色对象在本次垃圾回收之后将会被判定为应回收,即使其仍然被黑色对象所引用,这将造成对象消失的问题 + +##### CMS对该问题的解决方法 +CMS为了解决该问题,其采用了如下方案: +- 当为黑色状态的对象创建新引用时,对象将会重新变为灰色(通过写屏障实现) + +> 写屏障是垃圾回收器在应用线程修改对象引用时,插入的一段逻辑hook,其类似于拦截器,分为pre-write barrier和post-write barrier + ### Hotspot算法实现 #### 枚举根节点 在可达性分析中,需要通过GC Roots来查找引用链。可以作为GC Roots的节点有: diff --git a/regular expression/正则进阶语法.md b/regular expression/正则进阶语法.md index ef611fe..98c116c 100644 --- a/regular expression/正则进阶语法.md +++ b/regular expression/正则进阶语法.md @@ -1,3 +1,14 @@ +- [正则表达式](#正则表达式) + - [语法](#语法) + - [No Capturing Group `(?:regex)`](#no-capturing-group-regex) + - [Named Caputure Group `(?regex)`](#named-caputure-group-nameregex) + - [Atomic Grouping `(?>regex)`](#atomic-grouping-regex) + - [Negative Lookahead `(?!regex)`](#negative-lookahead-regex) + - [Positive Lookahead `(?=regex)`](#positive-lookahead-regex) + - [Negative Lookbehind `(?