cnzz网站排名是怎么做的网站建设需要学多久知乎
- 作者: 多梦笔记
- 时间: 2026年02月16日 06:48
当前位置: 首页 > news >正文
cnzz网站排名是怎么做的,网站建设需要学多久知乎,商城网站数据库,青岛市区网络制作公司上一篇#xff1a;08-JVM垃圾收集器详解
1.三色标记
在并发标记的过程中#xff0c;因为标记期间应用线程还在继续跑#xff0c;对象间的引用可能发生变化#xff0c;多标和漏标的情况就有可能发生。
这里我们引入“三色标记”来给大家解释下#xff0c;把Gcroots可达…上一篇08-JVM垃圾收集器详解
1.三色标记
在并发标记的过程中因为标记期间应用线程还在继续跑对象间的引用可能发生变化多标和漏标的情况就有可能发生。
这里我们引入“三色标记”来给大家解释下把Gcroots可达性分析遍历对象过程中遇到的对象 按照“是否访问过”这个条件标记成以下三种颜色
黑色 表示对象已经被垃圾收集器访问过 且这个对象的所有引用都已经扫描过。 黑色的对象代表已经扫描过 它是安全存活的 如果有其他对象引用指向了黑色对象 无须重新扫描一遍。 黑色对象不可能直接不经过灰色对象 指向某个白色对象。灰色 表示对象已经被垃圾收集器访问过 但这个对象上至少存在一个引用还没有被扫描过。白色 表示对象尚未被垃圾收集器访问过。 显然在可达性分析刚刚开始的阶段 所有的对象都是白色的 若在分析结束的阶段 仍然是白色的对象 即代表不可达。 /*** 垃圾收集算法细节之三色标记* 为了简化例子代码写法可能不规范请忽略* Created by 诸葛老师*/
public class ThreeColorRemark {public static void main(String[] args) {A a new A();//开始做并发标记D d a.b.d; // 1.读a.b.d null; // 2.写a.d d; // 3.写}
}class A {B b new B();D d null;
}class B {C c new C();D d new D();
}class C {
}class D {
}2.多标-浮动垃圾
在并发标记过程中如果由于方法运行结束导致部分局部变量(gcroot)被销毁这个gcroot引用的对象之前又被扫描过(被标记为非垃圾对象)那么本轮GC不会回收这部分内存。这部分本应该回收但是没有回收到的内存被称之为“浮动垃圾”。浮动垃圾并不会影响垃圾回收的正确性只是需要等到下一轮垃圾回收中才被清除。 另外针对并发标记(还有并发清理)开始后产生的新对象通常的做法是直接全部当成黑色本轮不会进行清除。这部分对象期间可能也会变为垃圾这也算是浮动垃圾的一部分。
3.漏标-读写屏障
漏标会导致被引用的对象被当成垃圾误删除这是严重bug必须解决有两种解决方案 增量更新Incremental Update 和原始快照Snapshot At The BeginningSATB 。 增量更新就是当黑色对象插入新的指向白色对象的引用关系时 就将这个新插入的引用记录下来 等并发扫描结束之后 再将这些记录过的引用关系中的黑色对象为根 重新扫描一次。 这可以简化理解为 黑色对象一旦新插入了指向白色对象的引用之后 它就变回灰色对象了。 原始快照就是当灰色对象要删除指向白色对象的引用关系时 就将这个要删除的引用记录下来 在并发扫描结束之后 再将这些记录过的引用关系中的灰色对象为根 重新扫描一次这样就能扫描到白色的对象将白色对象直接标记为黑色(目的就是让这种对象在本轮gc清理中能存活下来待下一轮gc的时候重新扫描这个对象也有可能是浮动垃圾) 以上无论是对引用关系记录的插入还是删除 虚拟机的记录操作都是通过写屏障实现的。
1.写屏障
给某个对象的成员变量赋值时其底层代码大概长这样
/**
- param field 某对象的成员变量如 a.b.d
- param new_value 新值如 null
/
void oop_field_store(oop field, oop new_value) { field new_value; // 赋值操作
} 所谓的写屏障其实就是指在赋值操作前后加入一些处理可以参考AOP的概念
void oop_field_store(oop field, oop new_value) { pre_write_barrier(field); // 写屏障-写前操作field new_value; post_write_barrier(field, value); // 写屏障-写后操作
}写屏障实现SATB 当对象B的成员变量的引用发生变化时比如引用消失a.b.d null我们可以利用写屏障将B原来成员变量的引用对象D记录下来
void pre_write_barrier(oop field) {oop old_value field; // 获取旧值remark_set.add(old_value); // 记录原来的引用对象
}写屏障实现增量更新 当对象A的成员变量的引用发生变化时比如新增引用a.d d我们可以利用写屏障将A新的成员变量引用对象D记录下来
void post_write_barrier(oop field, oop new_value) { remark_set.add(new_value); // 记录新引用的对象
}2.读屏障
oop oop_field_load(oop* field) {pre_load_barrier(field); // 读屏障-读取前操作return field;
}读屏障是直接针对第一步D d a.b.d当读取成员变量时一律记录下来
void pre_load_barrier(oop field) { oop old_value *field;remark_set.add(old_value); // 记录读取到的对象
}现代追踪式可达性分析的垃圾回收器几乎都借鉴了三色标记的算法思想尽管实现的方式不尽相同比如白色/黑色集合一般都不会出现但是有其他体现颜色的地方、灰色集合可以通过栈/队列/缓存日志等方式进行实现、遍历方式可以是广度/深度遍历等等。
对于读写屏障以Java HotSpot VM为例其并发标记时对漏标的处理方案如下
CMS写屏障 增量更新G1Shenandoah写屏障 SATBZGC读屏障 工程实现中读写屏障还有其他功能比如写屏障可以用于记录跨代/区引用的变化读屏障可以用于支持移动对象的并发执行等。功能之外还有性能的考虑所以对于选择哪种每款垃圾回收器都有自己的想法。
为什么G1用SATBCMS用增量更新 我的理解SATB相对增量更新效率会高(当然SATB可能造成更多的浮动垃圾)因为不需要在重新标记阶段再次深度扫描被删除引用对象而CMS对增量引用的根对象会做深度扫描G1因为很多对象都位于不同的regionCMS就一块老年代区域重新深度扫描对象的话G1的代价会比CMS高所以G1选择SATB不深度扫描对象只是简单标记等到下一轮GC再深度扫描。
4.记忆集与卡表 在新生代做GCRoots可达性扫描过程中可能会碰到跨代引用的对象这种如果又去对老年代再去扫描效率太低了。 为此在新生代可以引入记录集Remember Set的数据结构记录从非收集区到收集区的指针集合避免把整个老年代加入GCRoots扫描范围。事实上并不只是新生代、 老年代之间才有跨代引用的问题 所有涉及部分区域收集Partial GC 行为的垃圾收集器 典型的如G1、 ZGC和Shenandoah收集器 都会面临相同的问题。 垃圾收集场景中收集器只需通过记忆集判断出某一块非收集区域是否存在指向收集区域的指针即可无需了解跨代引用指针的全部细节。 hotspot使用一种叫做“卡表”(Cardtable)的方式实现记忆集也是目前最常用的一种方式。关于卡表与记忆集的关系 可以类比为Java语言中HashMap与Map的关系。 卡表是使用一个字节数组实现CARD_TABLE[ ]每个元素对应着其标识的内存区域一块特定大小的内存块称为“卡页”。 hotSpot使用的卡页是2^9大小即512字节
一个卡页中可包含多个对象只要有一个对象的字段存在跨代指针其对应的卡表的元素标识就变成1表示该元素变脏否则为0. GC时只要筛选本收集区的卡表中变脏的元素加入GCRoots里。 卡表的维护 卡表变脏上面已经说了但是需要知道如何让卡表变脏即发生引用字段赋值时如何更新卡表对应的标识为1。 Hotspot使用写屏障维护卡表状态。
下一篇10-JVM调优工具详解
相关文章
-
cnzz 网站域名怎么填网加商学院的wordpress
cnzz 网站域名怎么填网加商学院的wordpress
- 站长
- 2026年02月16日
-
cms做的网站胡源代码兰州装饰公司十强
cms做的网站胡源代码兰州装饰公司十强
- 站长
- 2026年02月16日
-
cms网站如何修改友情链接你会回来感谢我
cms网站如何修改友情链接你会回来感谢我
- 站长
- 2026年02月16日
-
cnzz站长统计怎么添加到博客网站广州开发区医院南岗院区
cnzz站长统计怎么添加到博客网站广州开发区医院南岗院区
- 站长
- 2026年02月16日
-
cn后缀做网站永川网站设计
cn后缀做网站永川网站设计
- 站长
- 2026年02月16日
-
cod建站系统中国北京门户网站建设调查报告
cod建站系统中国北京门户网站建设调查报告
- 站长
- 2026年02月16日
