当前位置: 首页 > news >正文

大连产品设计公司有哪些大连网龙建站优化推广

大连产品设计公司有哪些,大连网龙建站优化推广,如何更换网站服务器,怎么防止网站攻击大纲 1.Mixed GC混合回收是什么 2.YGC可作为Mixed GC的初始标记阶段 3.Mixed GC并发标记算法详解(一) 4.Mixed GC并发标记算法详解(二) 5.Mixed GC并发标记算法详解(三) 6.并发标记的三色标记法 7.三色标记法如何解决错标漏标问题 8.SATB如何解决错标漏标问题 9.重新梳…大纲 1.Mixed GC混合回收是什么 2.YGC可作为Mixed GC的初始标记阶段 3.Mixed GC并发标记算法详解(一) 4.Mixed GC并发标记算法详解(二) 5.Mixed GC并发标记算法详解(三) 6.并发标记的三色标记法 7.三色标记法如何解决错标漏标问题 8.SATB如何解决错标漏标问题 9.重新梳理Mixed GC的过程 10.选择CollectSet的算法是什么 11.Mixed GC的多次回收过程 1.Mixed GC混合回收是什么 (1)YGC的过程 (2)Mixed GC有那些步骤 (3)YGC和Mixed GC的关系 (4)Mixed GC的并发标记是从那些对象开始的 (1)YGC的过程 一.暂停系统程序运行 二.选择需要回收的Region 三.标记所有存活对象 四.复制对象操作 五.清理新生代所有垃圾释放Region (2)Mixed GC有那些步骤 Mixed GC(混合回收)主要有以下步骤 步骤一.初始标记阶段 标记出所有由GC Roots(及RSet)直接引用的对象会STW暂停程序运行。 步骤二.并发标记阶段 标记出在初始标记阶段标记的所有对象所引用的对象不会STW。 步骤三.最终标记阶段 这个阶段是标记出在并发标记阶段中没有被标记到的所有对象这些对象主要就是程序还在运行时产生的一些新对象会STW。 步骤四.存活对象计数 对每个Region区域中被标记的对象进行计数即统计出每个Region存活对象的数量和垃圾对象的数量。 步骤五.垃圾回收阶段 需要Stop the World这个阶段会选择性价比较高的Region。把这些Region的存活对象复制到新分区然后回收掉选择的那些分区。 前面分析YGC的转换关系时介绍过在YGC之后有可能会进入Mixed GC并发标记阶段。Mixed GC在某次YGC之后就直接开始进入并发标记阶段了。YGC、Mixed GC、FGC间的过程转换如下所示 (3)YGC和Mixed GC的关系 在YGC时会有GC Roots(局部变量 静态变量)标记这个步骤。在YGC的对GC Roots起始点进行标记的步骤中会把GC Roots直接引用的新生代对象  新生代的RSet作为起始点去标记。把新生代的RSet作为起始点是因为老年代有些定时任务可能创建新对象。 说明GC Roots(直接/间接)引用 被GC Roots(直接/间接)引用 但实际上GC Roots中并没有新生代、老年代的区分所以在新生代进行标记时会把所有GC Roots直接引用的对象都进行标记而进行处理时只会处理新生代。 YGC其实是Mixed GC的前奏或者说YGC是Mixed GC的初始标记阶段。从YGC、Mixed GC、FGC间的过程转换关系图可知某次YGC后可能会直接进入Mixed GC的并发标记阶段。所以当某次YGC结束后开启Mixed GC的并发标记那么就代表了Mixed GC已经完成了初始标记阶段这时可理解为YGC已处理完Mixed GC初始标记阶段的工作了。 (4)Mixed GC的并发标记是从那些对象开始的 一.如何找出新生代的所有存活对象 Mixed GC的并发标记阶段逻辑上应该是把GC Roots直接引用的对象的字段全部都遍历一遍。从而找到所有的间接引用的存活对象然后打上存活标记。这样就可以找出GC Roots直接引用 间接引用的所有新生代的存活对象。 但实际上Mixed GC中的并发标记阶段的实现却并不是这样。由于YGC会找出GC Roots引用的新生代对象以及RSet引用的新生代对象所以YGC后所有被GC Roots直接引用 间接引用的存活对象都在S区了并且老年代引用的新生代存活对象也全部在S区了。那么此时还剩下哪些对象需要全部找出来呢此时还需要找出剩下的老年代的所有存活对象。 二.如何找出老年代的所有存活对象 首先在GC Roots中直接引用的对象有一部分会在新生代中还有一部分会在老年代中。所以可以从GC Roots中直接获取直接引用的老年代对象这样就可以确定Mixed GC并发标记的起始点了Survivor区的对象  GC Roots直接引用的老年代对象  老年代的RSet。 注意Mixed GC初始标记的起始点(YGC并发标记的起始点)是GC Roots直接引用的新生代对象  新生代的RSet。 为什么要加上老年代的RSet因为Mixed GC的并发标记阶段不可能把整个老年代都遍历一遍。所以便可以用RSet作为起始点找到跨分区引用的引用链从而找到存活对象。 (5)总结 Mixed GC混合回收是什么 一.YGC的过程 二.Mixed GC有那些步骤 三.YGC和Mixed GC的关系 四.Mixed GC的并发标记是从那些对象开始的 五.Mixed GC的标记还需要做哪些内容 问题Mixed GC(混合回收)的标记还需要做哪些工作由于需要从老年代中选择一些性价比较高的区域来回收所以需要进行性价比相关的标记。那么性价比又应该怎么计算在MGC的并发标记阶段中会使用位图那么位图在并发标记阶段又应该怎么使用 2.YGC可作为Mixed GC的初始标记阶段 (1)YGC流程的一些细节调整 (2)YGC开始时判断是否开启并发标记的原因 (3)YGC可作为Mixed GC的初始标记阶段 (4)借助Survivor GC Roots记录即可完成老年代的标记 (1)YGC流程的一些细节调整 前面的YGC流程在最后一步才判断是否开启并发标记但这是不准确的。实际上在YGC开始时就会判断一下本次是否要尝试开启并发标记。因为如果当前老年代占用 本次分配对象已经超过45%的堆内存那么大概率在YGC最后一步就要开启并发标记了。所以这时在YGC开始时就可以直接设置一个Flag标记表示可以开启在YGC过程中就可以根据这个Flag标记提前并行把一些前置的工作做了。然后在YGC结束时结合其他的判断条件再尝试启动并发线程即可。 所以在YGC开始时判断是否要开启并发标记的一个原因通过设置一个Flag标记方便后续根据标记来执行一些处理(如前置工作)。 (2)YGC开始时判断是否开启并发标记的原因 由于Mixed GC并发标记的起始点是Survivor区的对象  GC Roots直接引用的老年代对象  老年代的RSet而且YGC又是Mixed GC的前置部分。 所以在YGC开始时判断是否要开启并发标记就能决定是否可以提前并行地把GC Roots引用的老年代对象进行处理处理好的这些老年代对象就可以在Mixed GC的并发标记线程启动时使用。 因此在进行YGC的GC Roots标记时其实还会有不同的情况。当发现不需要开启并发标记时会进行一套操作。需要开启并发标记时会进行另一套操作(记录直接引用的老年代对象)。 简单来说在YGC开始时判断是否要开启并发标记的另外一个原因判断YGC在处理GC Roots时是否要关注和处理直接引用的老年代对象。如果需要开启并发标记那么就关注处理否则就不用关注处理(注意GC Roots是不区分新生代和老年代的)。 YGC开始时判断是否要开启并发标记的原因 原因一通过设置一个Flag标记方便后续根据标记来执行一些处理(如前置工作)。 原因二判断YGC在处理GC Roots时是否需要关注和处理直接引用的老年代对象。 (3)YGC可以作为Mixed GC的初始标记阶段 在YGC阶段首先会判断是否需要开启并发标记。然后被GC Roots引用的新生代对象会被放入到Survivor区中。 同时如果发现需要开启并发标记那么一些被GC Roots直接引用的老年代对象也会被记录下来。 那么最终所有的GC Roots直接引用的对象一定都会被标记出来这样就可以把Mixed GC初始标记过程中所有需要的对象全都标记出来了因此YGC可以做为Mixed GC的初始阶段。 (4)借助Survivor GC Roots记录即可完成老年代的标记 在YGC中当发现需要开启并发标记当记录下被GC Roots直接引用的老年代对象后此时除了可以对引用了老年代对象的GC Roots做一些特殊处理之外还可以把Survivor对象 GC Roots引用的老年代对象 老年代RSet作为Mixed GC时执行并发标记的起始点。因为以它们作为并发标记的起点一定可以找到所有老年代的存活对象。 (5)总结 为什么YGC可作为Mixed GC的初始标记阶段 一.YGC流程的一些细节调整 二.YGC开始时判断是否开启并发标记的原因 三.YGC可作为Mixed GC初始标记阶段的原因 四.借助Survivor GC Roots记录即可完成老年代的标记 问题YGC是需要对所有新生代空间进行全部遍历然后回收的那么Mixed GC是否需要对整个老年代进行回收如果不需要应如何避免遍历整个老年代 答Mixed GC不需要对整个老年代进行回收但是Mixed GC需要对整个老年代进行全部标记。因为要挑选出性价比高的Region进行回收不标记全部就无法挑选出性价比较高的Region。 3.Mixed GC并发标记算法详解(一) (1)初始标记阶段给Mixed GC带来了什么 (2)对增量对象处理的一个简单思路 (3)对象分配的特性——连续性 (4)使用指针法来确定增量对象的范围 (1)初始标记阶段给Mixed GC带来了什么 根据前面的介绍可知初始标记阶段给了Mixed GC两块区域的内容 一.Survivor区的存活对象 二.GC Roots直接引用的老年代对象集合 通过这两组存活对象以及RSet的跨分区引用关系Mixed GC就可以完成所有存活对象的标记。 虽然这些起始点对象都拿到了可以通过这些起始点对象一个一个找到所有的存活对象。 但是因为是并发标记程序还在运行所以并发标记过程中系统程序还会产生一些新的对象这些新的对象并不在并发标记起始点对象的范围内那应如何判断这些新的对象是否是存活对象。 如下图示在并发标记的过程中新产生了一些对象。虽然针对这些对象进行一些增量标记即可但应怎么做这个增量标记G1的并发标记阶段又是怎么处理的呢 (2)对增量对象处理的一个简单思路 一个简单思路在并发标记阶段新创建的所有对象都存储到一个额外开辟的空间里。并发标记阶段结束后通过额外开辟空间里的对象标记所有存活对象。 但是这个思路肯定不太合适因为需要额外的空间而且如果程序运行的并发量比较高那么性能也会比较差。此外这些对象还可能造成原先被标记过的那些对象的引用关系发生变更从而需要额外维护这些新对象变更的引用关系。 (3)对象分配的特性——连续性 由于分配对象时会使用指针碰撞法分配对象 一个top指针代表TLAB已经使用到的内存 一个objSize代表分配对象需要的内存大小 一个end指针代表TLAB所占内存的结束位置 那么分配一个对象时占用的内存位置就是objSize top这说明进行对象分配时一定是线性的、连续的。 同时TLAB的分配和对象的分配其实使用的都是同一块代码。TLAB的分配和对象的分配都使用了指针碰撞法。 所以在同一个Reigon分配对象时Region中已使用的内存一定是连续的如下图示 可见不管在TLAB中还是在Region中内存的使用一定是连续的。如果有空的内存就会使用dummy对象进行填充。如果要记录并发标记阶段新产生的对象则可利用这种连续分配的特性。 (4)使用指针法来确定增量对象的范围 如果并发标记进行了一段时间在某一个Region里新对象以及已经被标记的对象会如下所示 其中红色的是已被标记的对象绿色的是新产生的对象。红色表示的已被标记的对象不一定存活只是说明被标记而已。 在并发标记开始到结束过程中这个Region的top指针一直指引着内存最终使用的位置。 于是G1就可以在并发标记后对Region这段标记前到标记后top位置变换的区域进行遍历标记这样就可以实现标记剩余的存活对象了。 从图中可以看出当并发标记结束后直接以并发标记前的top位置作为起始点遍历到并发标记后的top位置。这样就可以找到所有新创建的对象来判断其是否存活。 (5)总结 Mixed GC并发标记算法包括 一.初始标记阶段给Mixed GC带来了什么 二.对增量对象处理的一个简单思路 三.对象分配的特性—连续性 四.使用指针法来确定增量对象的范围 问题如何提升标记效率Mixed GC相当于需要遍历全部堆内存里的对象如果对每个对象打一个标签是否可行如果不打标签那么在垃圾回收时怎么办继续遍历对象吗 给每个对象打标签不可行因为要开辟额外的存储空间来进行专门存储。其实可以借助一些额外的存储结构来描述比如使用位图Bitmap。 4.Mixed GC并发标记算法详解(二) (1)为什么要使用位图 (2)与位图相关的指针(bottom指针 prev指针 next指针 top指针) (3)G1引入了哪些位图(PrevBitMap位图 NextBitMap位图) (1)为什么要使用位图 已知一个Region是一块连续的内存并且Region里面的对象分配、TLAB分配也都是连续的如下图示 基于上图进行如下分析 如果没有位图那么在每次标记时对于一个Region的处理只能是从头开始进行标记。因为不知道这个Region到底哪些地方被标记了、哪些地方没有被标记即使使用了top指针、end指针能找到并发标记开启前的对象使用位置也无法知道具体哪些对象被标记了、哪些没有被标记。要想知道具体哪些对象被标记了还是只能重新遍历所有对象。因此才需要一组数据告诉G1哪些内存被使用了、其中的对象是否被标记了、标记的状态又是什么。 所以为什么要使用一个额外的数据结构来描述标记情况其实就是为了快速拿到标记情况或者根据标记情况来快速进行清除操作。否则如果不记录标记情况的话那么即使标记过每次要使用时也只能通过遍历的方式获取。所以才需要把标记情况记录下来而位图就是比较合适的数据结构。 这样只要在BitMap标记好了并且没有新的改变那么每次都可以从BitMap中快速拿到标记的数据来直接使用。 (2)与位图相关的指针(bottom指针 prev指针 next指针 top指针) 前面已经介绍了top指针和end指针其实关于位图和并发标记过程的内存情况还有另外几个指针。 这几个指针分别代表的Region地址含义如下 bottom指针Region中内存使用的起始地址 top指针Region中内存使用的结束地址 prev指针上一次并发标记后处理到的地址 next指针这一次并发标记开始前已经使用的内存结束地址 end指针Region的结束地址 指针总结 一.bottom和end就是Region的起止地址 二.top指针会一直跟随对象分配的最新地址 三.prev指针是上一次并发标记处理到的地址 并发标记过程是有可能失败的这也是为什么会有多次并发标记的原因。即每一次并发标记并不一定都能走到最后成功完成一次并发标记的。所以就有可能会出现标记了一半然后标记被终止的情况。因此这个prev指针就是记录上一次执行并发标记时标记到的位置。 四.next指针 每次并发标记开始时next指针就会指向top。 并发标记开启后next指针会一直不变而top指针会随着新对象创建而不断移动。那么从next指针到top指针这段内存就是并发标记过程中新对象的内存。下一次并发标记开始时next指针又会指向top。 (3)G1引入了哪些位图(PrevBitMap位图 NextBitMap位图) 一.G1引入的两个位图(PrevBitMap位图和NextBitMap位图) 第一个位图叫PrevBitMap记录了从bottom指针到prev指针之间的内存区域里所有对象的标记状态。也就是记录了上一次并发标记时标记到的对象内存范围如下图示。这些标记状态会包括是否标记、是否存活等。 第二个位图叫NextBitMap记录了从bottom指针到next指针之间的内存区域里所有对象的标记状态如下图示 NextBitMap记录了本次并发标记过程中整个Region从开始到开启并发标记那个时刻的所有对象的标记状态也就是bottom指针到next指针这个范围内的内存使用的标记状态。 二.为什么有了NextBitMap位图还需要一个PrevBitMap位图 因为假如本次并发标记开始时发现上次并发标记失败了那就意味着本次并发标记要从bottom指针开始进行标记一直标记到next指针的位置。虽然上次并发标记是失败了但依然做出了一部分标记操作。所以本次并发标记其实还能继续使用它这就是需要PrevBitMap的原因(类似于断点续传)。 有了NextBitMap还需要PrevBitMap的原因总结如果进行了多次并发标记那么每次进行最新的并发标记时都可以接着上次并发标记的内容继续标记而不需要重新遍历从而大大节省了时间。如下图示 (4)总结 Mixed GC并发标记算法包括 一.初始标记阶段给Mixed GC带来了什么 二.对增量对象处理的一个简单思路 三.对象分配的特性—连续性 四.使用指针法来确定增量对象的范围 五.为什么要使用位图 六.与位图相关的指针(bottom指针 prev指针 next指针 top指针) 七.G1引入了哪些位图(PrevBitMap位图 NextBitMap位图) 5.Mixed GC并发标记算法详解(三) (1)进行第一次并发标记前(已完成初始标记) (2)进行第一次并发标记 (3)进行第二次并发标记 (1)进行第一次并发标记前(已完成初始标记) 此时bottom指针指向Region的起始位置top指针指向当前已经使用的内存的结束位置。 那么此时PrevBitMap是空的NextBitMap也是空的并且prev指针的位置和bottom指针的位置是一样的而且next指针的位置和top指针的位置是一样的。如下图示 (2)进行第一次并发标记 此时程序会不断运行创建新的对象同时并发标记也开始进行。那么位图会不断被补充并且top指针会不断移动。因为这是第一次标记PrevBitMap是不需要发生任何改变的只需要在NextBitMap中标记信息即可。如下图示在标记进行的同时prev指针也会不断的迁移。 假如此时标记失败那么只能进入到下一次并发标记。此时就会把NextBitMap给到PrevBitMap用于下一次并发标记使用。 (3)进行第二次并发标记 进行第二次并发标记时next指针会变化到top指针的位置prev指针会指向上一次并发标记时指向的位置。 那么此时NextBitMap就可以使用PrevBitMap中的一些标记信息了。 然后继续并发标记的后续过程。首先会在NextBitMap中把prev后next前的所有对象都给标记上。接着由于还在不断创建新对象所以会继续移动top指针。 此时并发标记就接近尾声了。 但还有一个问题这一次的并发标记和上一次的并发标记对PrevBitMap中标记的标记状态是有可能不一致的。比如上一次标记是被终止的终止后PrevBitMap标记的对象很可能更改引用关系或从存活变垃圾。所以实际的状态很可能是PrevBitMap和NextBitMap出现了不一致如下图示 那么应该如何解决这个问题怎么才能沿用上一次标记的状态同时又能保证标记是准确和一致的其实这个问题也是G1里面在并发标记阶段最难解决的问题。该问题不仅会发生在多次标记的场景下也会发生在并发标记的过程中。 怎么保证并发标记的NextBitMap一定是正确的怎么使用PrevBitMap来提升整体的标记效率为了解决PrevBitMap和NextBitMap不一致的问题G1引入了一个标记策略(三色标记法)和一个校对机制(SATB快照机制)来处理。 (4)总结 MixedGC并发标记算法包括 一.初始标记阶段给Mixed GC带来了什么 二.对增量对象处理的一个简单思路 三.对象分配的特性—连续性 四.使用指针法来确定增量对象的范围 五.为什么要使用位图 六.与位图相关的指针 七.G1引入了的位图有哪些 八.进行第一次并发标记前 九.进行第一次并发标记 十.进行第二次并发标记 6.并发标记的三色标记法 (1)三色标记法中的白、灰、黑 (2)从GC Roots出发开始进行对象的标记 (3)并发标记访问到C和D但C和D的Field还没被访问 (4)没子对象的对象标记为黑色有子对象的继续访问 (5)并发标记结束所有被GC Roots引用链引用到的对象都被标记为黑色 (1)三色标记法中的白、灰、黑 一.白色 白色代表当前对象没有被访问过如果在并发标记结束后某对象还是白色就代表它是垃圾对象可以被回收。 二.灰色 灰色代表当前对象已被访问到但Field字段没有被全部访问和标记完毕。即该对象是存活对象但是其引用的子对象还没有全都标记完成。 三.黑色 黑色代表当前对象已被访问到并且其Field也已被全部访问和标记完毕。 当并发标记阶段结束时所有的对象理论上要么是黑色、要么是白色即对象要么是垃圾对象、要么是存活对象。 并发标记未结束的某个时刻下对象的标记情况如下 接下来详细演示整个三色标记法的标记过程。 (2)从GC Roots出发开始进行对象的标记 构造一个如下的场景 对象是 A、B、C、D、E、F、G引用关系为 A.c C; B.c C;  B.d D; D.f F; F.g G; 其中的引用关系如下图示 首先GC Roots直接引用的对象会被标为黑色然后从GC Roots直接引用的这些对象出发开始标记对象。 为什么被GC Roots直接引用的对象能直接标记为黑色因为被GC Roots直接引用的对象是并发标记的起始点。这些对象是存活对象最终肯定成为黑色的。 (3)并发标记访问到C和D但C和D的Field还没被访问 此时C对象和D对象应该被标记为灰色。因为它们本身已经被标记但是它们的Field还没有被扫描标记。而EFG对象因为此时还没有被访问到所以还都是白色。 (4)没子对象的灰色对象标记为黑色有子对象的继续访问 此时C对象会被标记为黑色因为它没有引用其他对象。D对象因为只有一个Feild为F此时已经访问到F那么F会被标记成灰色。当一个对象的所有子对象被标记成灰色时对象本身就会被标记成黑色。 如下图示此时因为D的所有子对象(F)已经被标记为灰色了所以D被标记为黑色。而D的子对象F因为其Feild引用的对象G还没有被标记所以此时对象F的状态为灰色。 (5)并发标记结束所有被GC Roots引用链引用到的对象都被标记为黑色 接下来的过程和上面的流程类似就是把所有可达对象都进行访问标记。这样就可以把所有存活对象都标记成黑色而不可达对象就是保持白色。 ABCDFG对象的最终状态因为可达被标记黑色E对象因为不可达而保持白色。在垃圾回收时白色对象会被回收掉黑色对象会继续存活在堆内存中这就是三色标记法。 但是三色标记法本身并没有解决错标漏标的问题三色标记法仅仅描述对象在三种状态下的转变。那应该如何处理这些标记状态的转换来保证标记的正确性 (6)总结 并发标记的三色标记法 一.三色标记法中的白、灰、黑 二.三色标记法的对象转换过程 经过并发标记的整个阶段结束以后所有对象要么是黑色要么是白色。黑色的对象是存活对象白色的对象代表可以被回收。 7.三色标记法如何解决错标漏标问题 (1)标记出现漏标错标的条件 (2)对象的标记信息存储在NextBitMap中 (3)三色标记法是怎么解决错标问题的 (4)三色标记法如何解决错标漏标问题总结 (1)标记出现漏标错标的条件 条件一系统程序在并发标记阶段中添加了一个黑色对象到某白色对象的引用 也就是在一个被标记为黑色的对象上添加了一个到某白色对象的引用。因为黑色对象已经被标记了如果不重新扫描一下这个黑色对象那么这个白色对象将会被漏标这样程序运行就会出现错误。当然如果还有灰色对象在引用这个白色对象其实也无所谓。因为灰色对象的字段会被遍历重新找到这个白色对象进行标记这样就不会出错。 条件二系统程序在并发标记阶段中删除了所有灰色对象到该白色对象的引用 仅仅发生条件一还可能不会出现错标漏标但同时发生条件一 条件二那么就必然会出现错标漏标。 场景演示如下 一开始E这个对象没有任何引用。此时并发标记已经开始一段时间了系统也在不断地运行。 假如此时程序执行了一个操作F.g null; C.g G; 那么此时的引用关系就会变成如下所示 按照上面的思路分析如果此时不对C进行重新处理就会出现G被漏标的情况。因为C已经是黑色了说明是存活对象而且已经完成了标记。此时F正在标记过程中但是F已经不再引用G了那就会导致G被漏标从而最终造成程序错误。 所以这个错标漏标问题必须要解决而解决的思路之一就是利用三色标记法的状态转换来保证最终标记的正确性。 (2)对象的标记信息存储在NextBitMap中 G1引入了NextBitMap来标记对象的状态其实这些黑色、白色、灰色的状态就是存储在NextBitMap中。并发标记结束时所有白色状态的对象都可以回收。 注意NextBitMap记录了bottom指针到next指针范围内的内存使用的标记状态。 bottom指针Region内存使用的起始地址 next指针这一次并发标记开始前已经使用的内存结束地址 此时会有一个新的问题并发标记阶段产生的新对象怎么标记、存储在哪里 其实会在并发标记的下一个阶段(重新标记阶段)进行处理重新标记阶段会把所有产生的新的对象进行重新标记以及纠正在并发标记阶段造成的一些标记状态不正确的情况。 (3)三色标记法是怎么解决错标问题的 一.并发运行造成的错标漏标情景一 假如在并发标记过程中已经完成了C对象的标记了。但是此时执行了一个C.e E那么此时E对象也是一个可达对象。但是并发标记过程却没有标记到因为刚好错过了时间。并发标记标记完了C对象然后去干其他事情了而程序又执行了赋值操作。如下图示 此时E对象已经可达了但是却还是白色。如果该问题不解决就会导致E对象被回收掉在使用C对象时出现系统错误。 二.并发运行造成的错标漏标的情景二 假如第一次并发标记已经标记到C、D对象并且F已经被访问。此时CD都是黑色然后并发标记被终止于是只能进入下一次并发标记才能完成标记。此时的标记状态如下 在下一次并发标记开始前程序执行了D.e E此时E对象是可达的。但是在上一次被终止的并发标记中D对象已经被标记成黑色了。于是下一次并发标记开始后E对象的白色状态不会改变这样E对象在回收时就会被当作垃圾对象回收掉。 那么应该怎么解决错标漏标问题呢 三.三色标记法解决错标漏标问题 当程序修改某对象的引用关系时改变NextBitMap中该对象的标记状态。比如程序在执行了D.e E时则把NextBitMap中的对象D标记为灰色。然后在后续处理时再把灰色的对象重新执行一遍即可。 当把所有的灰色对象都重新遍历一遍后可能会产生一些新的垃圾对象。此时的最终状态如下这样就能保证最终标记的正确性了。 (4)三色标记法如何解决错标漏标问题总结 一.标记出现漏标错标的条件 在黑色对象上添加一个到白色对象的引用并且删除了所有灰色对象到该白色对象的引用。这可能发生在并发标记的程序运行时也可能发生在并发标记被终止后。 二.对象的标记信息存储在NextBitMap中 三.三色标记法如何解决错标问题(增量更新) 把改变了引用的对象在NextBitMap中的标记重新置为灰色然后在后续阶段再重新处理一下这个灰色对象的引用关系。 问题除了三色标记法本身可解决错标漏标问题外还有方法能解决该问题吗SATB是怎么解决这个错标漏标问题的 三色标记法本身解决 --- 增量更新。 SATB解决 --- 原始快照。 8.SATB如何解决错标漏标问题 (1)SATB的由来(PrevBitMap保存一份快照) (2)SATB是如何处理变化的引用关系的 (3)SATB如何记录对象(把对象放入SATB队列) (1)SATB的由来(PrevBitMap保存一份快照) PrevBitMap主要用于记录从bottom指针到prev指针之间的内存区域里所有对象的标记状态。即上一次并发标记阶段被中断时标记到的所有对象的标记情况。 bottom指针Region中内存使用的起始地址 prev指针上一次并发标记后处理到的地址 PrevBitMap的第一个作用是在并发标记开始时PrevBitMap会被复制到NextBitMap来提升效率。 PrevBitMap的第二个作用是由于PrevBitMap记录了上一次并发标记过程中的对象的标记情况所以在PrevBitMap中可以知道已处理对象的标记状态。 那么本次并发标记开始前以及开始后都有可能对已经标记好的那些对象做一些引用关系的改动于是可以通过PrevBitMap知道这些对象在引用关系改变前的标记状态。 比如在第二次并发标记开始前对象的标记状态如下 这个其实就是SATB快照的由来。基于上一次并发标记标记出的PrevBitMap就能知道对象的标记状态。根据PrevBitMap中记录的标记状态就可以决定是否要对当前对象处理。 (2)SATB是如何处理变化的引用关系的 当执行了F.g null; C.g G操作时对象的引用关系就会发生变化。 一.前面三色标记法自己的思路是增量更新 也就是把C这个对象先设置为灰色然后重新从C出发再来标记一次。 二.这里SATB方法的思路是原始快照 也就是把G这个对象先通过写屏障保存到一个地方。等到本轮次并发标记结束后再把这些保存的没有遍历标记到的对象再重新标记一次即可。此时会变成如下图示状态 此时对象的引用关系已经变了NextBitMap会自己继续处理自己的事继续往后标记。 SATB这种做法其实相当于把G这个对象置为灰色。而三色标记法最终是需要把所有的对象标记成白色或者是黑色的。所以灰色的对象是一定需要再重新处理一遍的此时标记状态如下图 当并发标记完成后在重新标记阶段就可以把这些在SATB队列里保存的对象拿出来进行可达性分析。 像CDF这些对象不需要重新标记只需要把G是否可达分析一下即可。所以对SATB队列里的对象进行可达性分析就能把全部对象正确标记上。最终整体的标记状态就会是如下图示 一.SATB队列已被清空 二.同时所有的存活对象、垃圾对象也都被标记在NextBitMap中 (3)SATB如何记录对象(把对象放入SATB队列) G1会通过写屏障实现把对象放入SATB队列中。即在执行一些引用更新操作把新对象赋值给老对象的某个字段前会把这个新对象写入到SATB队列中。 可以将写屏障理解成一段增强代码类似于AOP的思想当然这种AOP思想是通过写屏障来实现的。当C.g G被执行时就代表引用关系可能会发生变化了。而当出现引用关系变化时就会触发对象放入SATB队列这个操作。所以当C.g G被执行时对象G就会被写屏障识别并写入到SATB队列中。如下图示 G1为了解决错标漏标问题最终采用SATB方案来处理对象的重新标记。即BitMap  三色标记法  SATB快照  写屏障  SATB待处理对象队列从而保证对象在标记过程的准确性。 此外在处理RSet变更时也用到了写屏障即用增强代码来写一条变更的消息到DCQ里面。 9.重新梳理Mixed GC的过程 (1)初始标记阶段STW (2)并发标记阶段 (3)最终标记阶段STW (4)预回收阶段 (5)混合回收阶段 (6)Mixed GC的整体流程图 (1)初始标记阶段STW 首先Mixed GC一定会伴随一次YGC。在YGC时开始时会做一个判断看看是否需要开启并发标记。如果需要开启并发标记那么在本次YGC的过程中会额外做一些事情。比如把GC Roots直接引用的老年代对象也标记起来从而这些被标记的老年代对象可以作为并发标记阶段的起始对象的一部分。 Mixed GC的初始标记阶段会发生YGC。YGC结束后S区的对象会作为并发标记阶段的起始对象的一部分。 (2)并发标记阶段 YGC后会根据判定条件开启并发标记线程然后执行并发标记任务。然后从S区存活对象 GC Roots引用的老年代对象 RSet开始进行标记并通过位图NextBitMap 三色标记法来标记对象是否存活。然后通过SATB队列 写屏障把并发标记过程中的引用关系变化记下从而解决错标漏标的问题。 在三色标记法中白色代表垃圾、黑色代表存活、灰色代表存活但其子对象尚未完全遍历。 G1在做并发标记时是不是也是按照分区来进行的是的G1本身就是从分区出发来处理的。所以如果要找某个特定分区的所有存活对象需要借助RSet才能找到。 (3)最终标记阶段STW 最终标记阶段主要处理并发标记阶段由于系统运行造成的错标漏标问题。本质就是把SATB队列里的所有对象重新进行遍历标记处理。最终实现把全部对象都标记为黑色或者保持原本的白色。 最终标记阶段另外还会结束整个标记过程。因为在并发标记阶段是不会进行STW的。所以如果不引入这个重新标记阶段通过STW把所有对象都标记完成。那么并发标记阶段就会随着系统运行而持续不断地运行下去。 (4)预回收阶段 在最终标记阶段后会进入预回收阶段这个阶段会处理的事情如下 一.根据RSet NextBitMap完成存活对象计数并对Region排序 也就是统计每一个Region内部到底有多少对象存活、有多少垃圾对象。由于位图的存在可以根据位图中的标记数据把存活对象统计出来。完成存活对象的计数后会根据统计结果对Region进行排序。 二.更新标记位图PreBitMap 更新PrevBitMap是为下一次并发标记做准备(如果回收成功则忽略)。因为虽然某个Region在本次并发标记进行标记了但是未必会在混合回收中被选中所以才需更新一下PreBitMap以便Region在混合回收没选中时下一次标记还可用其标记过的位图。 三.重置RSet 此时老年代的分区已经完成标记。如果标记后的分区没有被对象引用说明引用已经改变此时就可以删除原来的RSet里的引用关系。 四.清理掉全部都是垃圾对象的分区然后把分区放到空闲分区列表中 需要注意这个阶段清理的分区只会针对所有对象都是垃圾对象的分区。对于存在存活对象的分区不会有任何操作。所以很可能在这个预回收阶段结束后JVM的内存使用情况没任何变化。 (5)混合回收阶段 在这个阶段JVM需要选择一些分区进行回收。这些被选中的分区就成为了CSet(Collect Set)。垃圾回收时会回收这些被选中的分区然后把这些分区中的存活对象复制到空闲的分区。复制完成后便会清理掉这些被选中的分区同时把清理完的分区放入到空闲列表中。 需要注意在选择CSet时是按照一定的选择算法来选择的。因为在上一个阶段已经统计出各分区的存活对象数量和垃圾对象数量选择CSet时就会根据各分区的存活对象数量和垃圾对象数量进行选择。 (6)Mixed GC的整体流程图 10.选择CollectSet的算法是什么 (1)回收性价比是怎么计算的 (2)回收时间是什么 (3)如何计算回收时间 (4)停顿预测模型结合统计排序选择CollectSet (5)总结 (1)回收性价比是怎么计算的 G1在Mixed GC时会选择回收性价比最高的Region那性价比会怎么算 性价比 从该Region中可以回收掉的垃圾 / 回收该Region所需要的时间 比如一个Reigon总计32M存活对象12M垃圾对象20M。 复制12M存活对象 清空20M垃圾对象 清空12M已复制的对象 1ms 复制完12M对象到新Region后可以回收掉的空间是12M 20M32M那么这个Region的回收价值即性价比就是32M/ms。 因此对于一个Region来说 垃圾对象越多复制存活对象到新Region时间越少回收性价比越高。 存活对象越多复制存活对象到新Region时间越大回收性价比越低。 (2)什么是回收时间 可回收垃圾的数量可以通过位图NextBitMap来进行统计。因为位图标记了对象的存活状态同时也描述了对象占用空间的大小。 那么回收时间应该如何确定呢 首先回收时间更加准确的说法应该是存活对象的转移时间。YGC和MixedGC都采取复制算法把存活对象复制到一个空闲的新分区。然后再进行分区清理把清理的分区加入到空闲分区列表中。所以真正耗时的其实就是这个存活对象复制的过程。 因为对象复制涉及到了对象本身和对象数据的复制、对象头更新、引用关系的指向更新、RSet和卡表等一系列的更新所以对象复制这个过程是非常耗时的。 完成对象复制后可以认为原来的Region里都是垃圾对象了。此时直接全部进行清空处理基本不会耗费多少时间。 所以真正决定回收时间的就是存活对象的转移时间。因此可以认为垃圾回收需要的时间  存活对象的转移时间。 注意对存活对象进行复制所消耗的时间其实占了GC绝大部分的时间。 (3)如何计算回收时间 根据前面介绍的停顿预测模型可知在每次GC时都会对整个GC耗费的时间回收的垃圾数量进行统计用来预测下一次GC时应该选择多少分区回收多少对象。 停顿预测模型里的预测内容和对象转移效率基本上是同一个意思。根据停顿预测模型预测出来的对象回收能力  单位时间回收多少对象对象回收能力其实就是对象转移效率。 对象转移效率(单位时间转移多少对象/单位时间回收多少对象)如果一个Region中的存活对象越多或越大那它需要的转移时间就越多。​​​​​​​ Region的存活对象大小 / 单位时间转移多少对象 转移时间Region的存活对象大小 / 单位时间回收多少对象 回收时间 如下图示有三个Region第一个Region的存活对象只有一个转移起来会比较容易耗费的时间最短。第二个Region转移起来会比较麻烦耗费的时间最长。 对象转移的过程首先需要把存活对象复制到一个空闲分区然后执行一系列RSet更新、卡表更新、对象引用更新等操作把原Region里的存活对象复制到一个空闲Region后就可以清理掉原Region的所有对象了。 (4)停顿预测模型结合统计排序选择CollectSet 选择Collect Set的算法其实就是结合一 二就可以选择出性价比高的Region进行回收。 一.根据停顿预测模型计算出对象转移效率(单位时间转移多少对象) 二.在Mixed GC的预回收阶段得到Region垃圾对象和存活对象的统计排序 简单来说就是 垃圾对象越多、存活对象越少的Region回收时间就越少性价比越高。 Collect Set的选择算法就是选择垃圾对象越多的那些Region来回收。 (5)总结 对于这个问题首先要说明的就是回收性价比。回收性价比  Region中可回收的垃圾 / 回收一个Region所需要的时间。所以回收性价比就是单位时间内能回收多少垃圾回收越多性价比越高。 注意存活对象复制到新Region后就相当于变成了垃圾对象。 Region中会有对象转移效率这个概念。对象转移效率可以看成是停顿预测模型中预测的回收能力因此停顿预测模型预测的回收能力可代表Region的存活对象的转移效率。注意停顿预测模型预测的回收能力是基于衰减标准差的。 那么Mixed GC的混合回收阶段在选择Region时就可以基于并发标记阶段的标记内容以及最终标记阶段对Region存活对象的统计然后按照存活对象数量多少来选择Region其中存活对象越少的Region就会越被选中。 假设Region大小4M停顿预测模型计算出单位时间可以回收2M对象也就是对象回收能力 2M/s或者对象转移效率 2M/s​​​​​​​ 第一个Region的存活对象1M转移完存活对象、回收完1M需要时间 1M 除以 2M/s 0.5s第二个Region的存活对象2M转移完存活对象、回收完2M需要时间 2M 除以 2M/s 1s第三个Region的存活对象3M转移完存活对象、回收完3M需要时间 3M 除以 2M/s 1.5s由于每个Region总共可以回收的垃圾 垃圾对象 存活对象(因为转移到另一个Region了) 4M第一个Region的性价比单位时间可以回收垃圾4M 除以 0.5s 8M/s第二个Region的性价比单位时间可以回收垃圾4M 除以 1s 4M/s第三个Region的性价比单位时间可以回收垃圾4M 除以 1.5s 2.7M/s 11.Mixed GC的多次回收过程 (1)被选中的CSet (2)加入CSet的Region的存活对象不能太多 (3)CSet可回收比例判断Mixed GC是否执行 (4)Mixed GC会对CSet进行分批次混合回收 (5)分批次的混合回收选择的Region个数限制 (1)被选中的CSet 因为Mixed GC本身是包含了YGC的所以Mixed GC在选择Region时一定是包含了所有的新生代分区。虽然Mixed GC在初始标记阶段已通过YGC完成了对新生代的回收。但本质上一次Mixed GC混合回收选择的分区还是包含了新生代所有分区以及老年代的部分分区。 另外还需注意在Mixed GC混合回收阶段被选中的Region不会出现里面全是垃圾因为里面全是垃圾的Region在预回收阶段已经被清理掉了。 那么当全是垃圾的Region被清理掉后剩下的Region到底选多少才合适虽然G1会选择性价比高的Region但性价比高的Region又应选择多少 (2)加入CSet的Region的存活对象不能太多 -XX:G1MixedGCLiveThresholdPercent 这个参数决定了是否可以把一个Region加入到CSet集合中。这个参数的含义是一个Region的存活对象占这个Region的比例如果大于或等于该参数值时就不加入到CSet中。如果小于该参数值就可以加入到CSet中。 这个参数的默认值是85%。即如果存活对象大于或等于85%Region大小那么这个Region就不值得回收不能加入CSet。这时该Region的回收价值太低了因为大量对象需要被复制到新的分区特别耗时且腾出来的空间又很小。 (3)CSet可回收比例判断Mixed GC是否执行 -XX:G1HeapWastePercent 真正执行混合回收阶段对Region的回收是在并发标记阶段完成后。而在真正执行混合回收阶段前其实还需要做一层额外的判断。 注意这个判断和是否开启并发标记的判断不是一个意思。这个判断是发生在并发标记之后决定是否要开始进行回收。 这个判断由-XX:G1HeapWastePercent参数控制默认5%。即在并发标记结束后如果选择的CSet中可被回收的垃圾占堆内存总空间的比例大于5%才会开始混合回收的回收阶段否则本次是不开启垃圾回收过程的。即使并发标记阶段、最终标记阶段都已经完成也不开启混合回收过程。 (4)MixedGC会对CSet进行分批次混合回收 -XX:G1MixedGCCountTarget 在判断通过之后就会进入这最后一步的混合回收阶段。这个阶段因为要控制停顿时间所以G1会分开多次执行。 具体几次是由一个参数控制-XX:G1MixedGCCountTarget默认为8。混合回收的过程会对CSet进行分批次回收最多分8次来完成混合回收。 假如CSet总共有400个Region每次为了满足停顿时间(假设100ms)发现只能回收50个那么就会按照每次50个左右的Region来进行回收。因为按照Region的性价比排序所以可能每次能回收的个数不一定是50。 当然这个8次是不一定会完全进行到底的。当G1分批次回收时会判断要不要进行下一次回收判断的条件还是-XX:G1HeapWastePercent。也就是每执行一次混合回收就会判断一下CSet里的垃圾对象占用的空间是否大于堆内存的5%。如果小于就停止混合回收本次回收就彻底结束如果大于则继续进行 如果CSet里的Region非常多每次选择的Region也非常多这时该如何 (5)分批次的混合回收选择的Region个数限制 -XX:G1OldCSetRegionThredShouldPercent这个参数默认是10表示每次在执行混合回收时回收掉的分区数量不能超过整个堆内存分区数量的10%。 假如分了8次进行回收结果发现某一次回收时准备回收300个分区。而此时堆内存总共才2000个分区那么此时是不会回收300个分区而是只会回收200个分区。 (6)总结​​​​​​​ 1.加入CSet的Region存活对象占比不能太多——XX:G1MixedGCLiveThresholdPercent2.混合回收是否要执行的判断条件之CSet可回收空间比例——XX:G1HeapWastePercent3.MixedGC会对CSet进行分批次的混合回收——XX:G1MixedGCCountTarget4.分批次的混合回收选择的Region个数限制——XX:G1OldCSetRegionThredShouldPercent
http://www.w-s-a.com/news/317228/

相关文章:

  • 哪些行业做网站的多学企业网站开发
  • 外贸seo网站制作网站备案的流程
  • 网站布局教程wordpress 侧边栏位置
  • 谁有手机网站啊介绍一下dedecms 网站重复文章
  • 博客网站快速排名微信机器人免费版wordpress
  • 孝感网站建设xgshwordpress网站基础知识
  • 百度为什么会k网站长沙做网站找哪家好
  • 揭阳商城网站建设新闻稿发布平台
  • 电商网站建设免费在线优化网站
  • 厦门网站建设咨询挣钱最快的小游戏
  • 郑州网站网络营销莱芜雪野湖别墅
  • 安装iis8 添加网站河南省建设执业资格中心网站
  • 个人网站电商怎么做广州市营销型网站建设
  • 空间站做网站什么版本wordpress 勾子
  • win7网站服务器制作软件网站浏览图片怎么做的
  • 网站制作平台公司嵌入式软件开发环境
  • 网站服务器镜像微商做网站网站
  • 十大旅游电子商务网站网上定做衣服
  • 怎样进行网站备案上海发布公众号app
  • 网站后台模板论坛网站优化招商
  • 个人网站设计作品能用VUE做网站
  • 网站建设预付阿里云域名备案查询
  • 苏州本地网站免费咨询医生的软件
  • 个人网站做废品回收福建网站开发招聘
  • wordpress网站备案学设计常用的网站
  • 网站建设的频道是什么网站用什么开发软件做
  • 电子商务网站建设与规划总结外链查询网站
  • 西安网站品牌建设做网站需要的东西
  • 网站外围网站怎么做移动端网站开发项目
  • 做网站只做前端可以用吗知更鸟免费 wordpress