java中的垃圾回收器
垃圾回收器垃圾回收集器分新生代收集器、老年代收集器、组合收集器JDK8 默认Parallel Scavenge Parallel OldJDK9 开始默认 G1新生代Serial串行收集器单线程STW标记复制。适用客户端、单核小应用。缺点STW 时间长。启动参数-XX:UseSerialGCParallel ScavengePS并行回收多线程标记复制。目标吞吐量优先。吞吐量 运行用户代码时间 / (用户代码 GC 时间)。搭配老年代Parallel Old。参数-XX:UseParallelGCParNew多线程标记复制。和 PS 算法一样但可以和 CMS 配合PS 不能和 CMS 搭配。JDK8 以前 CMS 默认新生代收集器。参数-XX:UseParNewGC老年代Serial Old单线程标记整理。用途客户端CMS 失败时的降级备用收集器。Parallel Old多线程标记整理吞吐量优先。搭配 PS。JDK8 默认组合PS Parallel Old。CMSConcurrent Mark Sweep并发标记清除低延迟并发标记 清除会产生内存碎片。阶段初始标记 (STW) → 并发标记 → 重新标记 (STW) → 并发清除缺点内存碎片Full GC 后需要整理浮动垃圾并发失败Concurrent Mode Failure触发 Full GC退化 Serial Old占用 CPU。JDK9 开始废弃 CMS。参数-XX:UseConcMarkSweepGC整堆收集器新生代 老年代一起回收G1Garbage-First分区模型Region不再严格分新生代老年代可预测停顿。算法标记整理整体无碎片局部标记复制。目标兼顾吞吐量和低延迟。优先回收垃圾最多的 Region。JDK9 默认 GC。参数-XX:UseG1GCZGCZ Garbage CollectorJDK11 引入JDK15 正式启用。目标极低延迟STW 几乎 ms 级。染色指针读屏障几乎全并发。最大堆支持 TB 级。几乎没有 STW。JDK17 推荐生产使用。参数-XX:UseZGCShenandoahRedHat 开发和 ZGC 类似低延迟不需要移动对象时的读屏障用转发指针。JDK12 引入OpenJDK。对比表收集器代算法特点目标缺点Serial新生标记复制单线程简单小内存STW 长Parallel Scavenge新生标记复制多线程吞吐量优先停顿时间不可控ParNew新生标记复制多线程配合 CMS已慢慢淘汰Serial Old老年标记整理单线程兜底回收STW 很长Parallel Old老年标记整理多线程吞吐量优先停顿不可控CMS老年标记清除并发低延迟碎片、并发失败JDK9 废弃G1整堆标记整理 复制分区 Region可控停顿大堆场景性能不如 ZGCZGC整堆染色指针全并发亚毫秒级 STWCPU 消耗略高Shenandoah整堆转发指针全并发低延迟生态不如 ZGC 成熟垃圾回收器执行流程CMS(Concurrent Mark Sweep并发标记清除)CMS 是老年代收集器目标低延迟尽量并发减少 STW算法标记清除会产生内存碎片。搭配新生代ParNew。JDK9 开始废弃。核心只有两个阶段 STW其余阶段 GC 线程和业务线程并发执行初始标记-并发标记-重新标记-并发清除1. 初始标记Initial Mark【STW很短】只标记GC Roots 直接可达的对象第一层对象不会递归遍历整个对象图。暂停所有用户线程。因为只扫根直接引用速度很快。2. 并发标记Concurrent Mark【并发无 STW】GC 线程和业务线程同时运行。从初始标记得到的根对象开始递归遍历整个老年代对象图标记所有存活对象。⚠️ 并发阶段业务线程还在修改引用会产生漏标问题。CMS 使用增量更新方案解决漏标如果黑色对象新增指向白色对象的引用写屏障把这个黑色对象记录到灰色栈留到 Remark 阶段重新扫描。3. 重新标记Remark【STW时间波动大】处理并发标记阶段产生的漏标对象。扫描灰色栈里记录的对象重新遍历它们的引用补标记存活对象。这个阶段 STW 时间不确定如果并发阶段大量新增引用灰色栈很大STW 会明显变长。4. 并发清除Concurrent Sweep【并发无 STW】GC 线程和业务线程并发运行。遍历堆把未被标记的对象当成垃圾直接回收不移动存活对象。算法是标记清除不会整理内存会产生内存碎片。G1Garbage-FirstG1Garbage-First分区 Region 模型整堆收集器目标可预测停顿。GC 分为两类Young GC、Mixed GC尽量避免 Full GCFull GC 是退化单线程 Serial OldSTW 很长G1 采用SATB 原始快照解决三色标记漏标。Young GC年轻代回收触发条件Eden 区耗尽。STW暂停业务线程标记 Eden、Survivor 里存活对象复制存活对象到 Survivor Region对象年龄增加达到阈值晋升到老年代 Region清空 Eden只回收年轻代 Region不处理老年代Mixed GC 的初始标记会依附在 Young GC 末尾复用这次 STW减少一次停顿Mixed GC混合 GCG1 核心老年代占比达到 IHOP 阈值触发一次性回收部分年轻代 部分垃圾最多的老年代 Region一共 4 个阶段初始标记Initial Mark【STW】依附在 Young GC 之后复用 STW。只标记 GC Roots直接可达对象。并发标记Concurrent Mark【并发业务线程继续跑】GC 线程和用户线程并发从初始标记的对象遍历整个堆标记存活对象。当业务线程删除 / 覆盖引用SATB 写屏障会把旧对象压入 SATB 队列防止漏标。产生浮动垃圾快照时刻存活但并发阶段已经失效的对象本次 GC 不能回收。最终标记Remark【STW】短暂暂停处理 SATB 队列剩余对象完成全部存活对象标记。筛选回收Cleanup Evacuation【STW】① 对所有 Region 按垃圾占比排序② 根据-XX:MaxGCPauseMillis目标停顿时间挑选垃圾最多的一批 Region③复制存活对象到空闲 RegionEvacuation 转移④ 清空这批 Region。因为是复制存活对象所以不会产生内存碎片。⚠️ Mixed GC ≠ Full GCMixed GC 只挑选部分老年代 Region 回收不是全部老年代。G1如何解决三色指针漏标问题G1 使用SATB 写屏障解决三色标记漏标问题。SATB 的核心思想在初始标记完成那一刻拍一个逻辑快照凡是快照时刻存活的对象本轮 GC 一律当成存活不允许被漏标回收。漏标必要条件黑色对象新增引用指向白色对象灰色对象指向该白色对象的全部引用被删除SATB 写屏障只拦截「引用删除 / 覆盖」操作。当业务线程执行obj.field null或者覆盖旧引用判断被删除的旧引用指向的对象是否是快照内对象地址 ≤ TAMS如果是快照内对象 → 把这个对象压入SATB 队列如果是快照后新建对象TAMS→ 不处理重点SATB不捕获新增引用只捕获删除快照内对象的引用。TAMSTop At Mark Start标记开始时的 Region 分配顶指针G1 专属在Mixed GC 初始标记完成瞬间给每一个 Region 记录下当时 Region 的top值。先搞懂 Region 里的两个指针bottomRegion 内存起始地址top对象分配游标新对象从 top 往后分配top 前面是已经分配的对象top 后面是空闲空间。Region 内存bottom | 已分配对象 | top | 空闲空间 | endTAMS 的作用在初始标记完成快照点G1 对每个 Region 保存TAMS 当前Region.top以此划分 Region 内两类对象对象地址 ≤ TAMS快照前分配的对象快照内对象SATB 保护范围。删除这类对象的引用写屏障会把对象压入 SATB 队列。对象地址 TAMS快照之后并发标记阶段新建的对象快照外对象不受 SATB 保护。删除它的引用写屏障不做任何处理。✅ G1 判断对象是否属于快照内对象底层就是比较对象地址和所属 Region 的 TAMS。ZGC(Z Garbage Collector)ZGC低延迟并发垃圾收集器目标亚毫秒级 STW堆可以支持 TB 级。核心技术染色指针Colored Pointers 读屏障Load BarrierZGC 是并发标记 并发转移复制全程几乎不 STW。ZGC 没有分代不区分新生代老年代没有 Region是 Page 页管理。三色标记保护读屏障和 G1 SATB、CMS 增量更新不一样。ZGC 一次 GC 分为 4 大阶段只有初始标记、再标记两个极短 STW 阶段STW 时间和堆大小无关只和 GC Roots 数量相关。1. 初始标记Pause Mark Start【STW极短】暂停所有业务线程。只扫描GC Roots标记 Root 直接可达对象。✅ STW只找根不递归遍历对象图。2. 并发标记Concurrent Mark【并发业务线程正常跑】GC 线程和业务线程并发执行。从 Root 对象开始遍历整个对象图标记存活对象。读屏障发挥作用业务线程读取对象引用时触发读屏障检查指针染色状态如果对象正在被移动读屏障会转发到新地址保证拿到正确对象。ZGC 靠读屏障解决并发标记时的对象引用变化问题。3. 再标记Pause Mark End【STW极短】短暂 STW处理并发标记阶段遗留的少量引用完成存活对象标记。这是第二轮 STW时间很短。标记阶段到此结束。4. 并发转移Concurrent Relocate【并发业务线程正常跑】ZGC 挑选垃圾多的 Page准备回收。并发把存活对象复制转移到新 Page类似复制算法。对象复制完成后旧对象指针保留染色标记后续业务线程访问旧地址时读屏障自动转发到新对象地址等所有引用都更新到新地址旧 Page 直接释放回内存。转移全程并发不会 STW。补充并发转移完成后还有一个并发重置Concurrent Reset重置 Page为下一轮 GC 做准备并发执行。ZGC如何解决三色指针漏标问题ZGC 使用「读屏障 染色指针Colored Pointers」来解决并发标记漏标采用的是读快照Load Barrier方案。ZGC 要保证标记开始那一刻存活的对象本轮 GC 一定全部标记不能漏。ZGC 核心染色指针Colored PointerZGC 在对象引用指针本身借用地址高位几个 bit 存标记状态Marked0Marked1Remapped不是对象头是指针本身。所以 ZGC 要求操作系统是64位且堆不能超过 4TB否则地址位不够。通过染色指针ZGC 可以不用去对象头直接从指针就能判断对象标记状态。ZGC 的读屏障Load BarrierZGC 没有写屏障G1/CMS 是写屏障ZGC 用读屏障。读屏障每当业务代码读取对象引用的时候触发一小段逻辑。当线程读取引用obj.field读屏障会检查如果这个指针是未标记的快照内对象白色立刻把这个对象标记成存活并且递归标记它的子对象。ZGC并发标记核心规则ZGC 在标记开始选定本轮标记版本Marked0 / Marked1二选一交替使用。对象在标记开始前分配对象引用指针上没有本轮标记版本 →快照前对象本轮需要标记保护防止漏标。对象在标记开始之后分配分配的时候直接把这个新对象的指针标记为本轮已标记Marked0/Marked1。新对象出生即标记为存活本轮 GC 不会去扫描、回收它直接交给下一轮 GC。标记举例GC 周期 A 启动选择本轮标记版本Marked0标记开始前对象 C 已经分配指针无 Marked0 标记 →快照内对象并发标记期间业务 new 对象 B分配时直接打上Marked0→快照后对象读屏障读到 CC 没有 Marked0属于快照内对象如果白色就标记存活读屏障读到 BB 自带 Marked0快照后对象直接放行不处理等到下一轮 GC 周期 B切换标记版本为Marked1。此时 B 上面的 Marked0 就不再是本轮标记B 就变成本轮快照内对象。怎么防止漏标漏标发生的根源业务删掉灰色引用同时黑色新增指向白色快照对象GC 看不到。在 ZGC只要业务线程读取这条黑色对象指向白色对象的引用读屏障就触发当场把白色对象标记存活。 只要这条引用被业务访问一次对象就被标记不会丢失。ZGC 的快照承诺标记开始时存活的对象本轮必须保留。标记开始之后新创建的对象本轮 GC 完全不处理全部留给下一轮 GC和 G1 不一样。

相关新闻

Python教程-Python中的基本命令 | 魔术命令

Python教程-Python中的基本命令 | 魔术命令

关于在教程里面提到的那些基本命令, 还有魔术命令的具体用法介绍。当它在1991年首次引入的时候, 普遍认为是属于自负风险的类型的一种语言。但是现在的情况已经改变了, 它已经成为了一种主导性的语言, 并且被用于数据科学领域、机器学习领域以及软件开发领域。大家都清楚, 它是…

2026/9/24 17:44:42 阅读更多 →
Vercel造Agent框架eve!未来网站得为Bot优化

Vercel造Agent框架eve!未来网站得为Bot优化

这意味着这个事物正在发生一种变化, 这种变化的方向是成为Agent。在最近我阅读了一篇相关的采访文章, 在仔细观看与阅读之后, 我的脑海里始终都在反复盘旋着这样的一句话, 它让我难以忘怀。> " are a new type of . They are not as as web ."说出这句话的那个人叫…

2026/9/24 17:44:42 阅读更多 →
万象棋谱-王者万象棋wiki百科:85 英雄全阵营、机制冷知识与流派克制一查便知

万象棋谱-王者万象棋wiki百科:85 英雄全阵营、机制冷知识与流派克制一查便知

《王者万象棋》9 月 10 日全平台上线后,最多的搜索就是「王者万象棋wiki」「王者万象棋图鉴」——85 名英雄、6 大阵营、78 件装备、254 张天赋、99 张效果牌,再加上拍卖、觉醒、词条联动这些新机制,光靠游戏内说明根本记不住。这篇文章就把 …

2026/9/24 17:44:41 阅读更多 →

最新新闻

Flutter for OpenHarmony单元测试:用mocktail实现无代码生成的Mock方案

Flutter for OpenHarmony单元测试:用mocktail实现无代码生成的Mock方案

在 Flutter for OpenHarmony 这类适配型工程里做单元测试,最让人头疼的往往不是业务逻辑本身,而是环境依赖。我最早在一个鸿蒙设备的 Flutter 项目里跑flutter test,第一轮测试就全被MissingPluginException淹没——原因很简单:测…

2026/9/24 18:30:15 阅读更多 →
医院信息系统Word导入组件选型与Java集成实战指南

医院信息系统Word导入组件选型与Java集成实战指南

在医院信息化行业摸爬滚打这些年,我被人问得最多的一句话就是:医生那边拿过来的Word,到底怎么才能干净地弄进咱们系统里。问这话的,有信息科刚入职的年轻人,也有集成商里天天被项目追着跑的实施工程师。这句话往深了挖…

2026/9/24 18:30:15 阅读更多 →
若依整合AI实战:SSE流式响应与Docker部署压测

若依整合AI实战:SSE流式响应与Docker部署压测

接手这个“若依整合AI”的实战改造前,我心里很清楚:业务方说“就加个聊天窗口”,实际意味着模型接口对接、流式响应、权限控制、异常兜底、部署压测这五件事一个都不能少。这篇文章是若依整合AI系列的第二篇,上一篇把大模型API选型…

2026/9/24 18:30:15 阅读更多 →
Python+Pygame游戏开发:从AABB到像素级碰撞检测全解析

Python+Pygame游戏开发:从AABB到像素级碰撞检测全解析

我刚开始用Python做游戏的那阵子,最爱看别人炫耀炫酷的特效和流畅的动画,可自己上手才发现,最磨人的不是画面,而是碰撞检测。明明角色已经走到金币面前,却愣是没触发得分;子弹看似打中了敌人,敌…

2026/9/24 18:30:15 阅读更多 →
跨平台终端文件管理器 Yazi 实测:从安装到美化,彻底告别 Windows 资源管理器

跨平台终端文件管理器 Yazi 实测:从安装到美化,彻底告别 Windows 资源管理器

"Windows 自带的文件资源管理器,说句难听的,我忍它很多年了。它倒也不是不能用,但你一旦开始批量整理照片、快速在两个目录间搬运文件、同时要看十几个不同类型的文件预览时,那种迟钝又局促的交互,总会让你觉得这…

2026/9/24 18:30:15 阅读更多 →
JSP+MySQL个人日记本源码运行全攻略:从环境搭建到避坑指南

JSP+MySQL个人日记本源码运行全攻略:从环境搭建到避坑指南

简介:基于jspmysql的JSP个人日记本源码,是一份面向Java Web初学者与课程设计场景的完整Web应用项目。资源以JSP作为视图层、Servlet处理控制逻辑,结合MySQL存储用户、日记与分类数据,覆盖用户登录、会话保持、日记增删改查、分类管…

2026/9/24 18:29:14 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →