<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>GC on 小蜜蜂</title>
        <link>https://xumf.net/tags/gc/</link>
        <description>Recent content in GC on 小蜜蜂</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Wed, 18 Jul 2018 15:43:54 +0800</lastBuildDate><atom:link href="https://xumf.net/tags/gc/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>垃圾回收器</title>
            <link>https://xumf.net/blog/garbagecollector/</link>
            <pubDate>Wed, 18 Jul 2018 15:43:54 +0800</pubDate>
            <guid>https://xumf.net/blog/garbagecollector/</guid>
            <description>&lt;h2 id=&#34;一jvm-垃圾回收器概述&#34;&gt;一、JVM 垃圾回收器概述&#xA;&lt;/h2&gt;&lt;p&gt;常见的垃圾回收器：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Serial GC&lt;/li&gt;&#xA;&lt;li&gt;Parallel GC（Throughput GC）&lt;/li&gt;&#xA;&lt;li&gt;CMS GC（Concurrent Mark Sweep）&lt;/li&gt;&#xA;&lt;li&gt;G1 GC（Garbage First）&lt;/li&gt;&#xA;&lt;li&gt;ZGC（Z Garbage Collector）&lt;/li&gt;&#xA;&lt;li&gt;Shenandoah GC&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;二垃圾回收器的特点与回收流程&#34;&gt;二、垃圾回收器的特点与回收流程&#xA;&lt;/h2&gt;&lt;h3 id=&#34;衡量-gc-优劣的三个核心指标&#34;&gt;衡量 GC 优劣的三个核心指标&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;吞吐量（Throughput）&lt;/strong&gt;：用户代码运行时间 /（用户代码运行时间 + GC 时间）。越高越好。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;暂停时间（Pause Time / Latency）&lt;/strong&gt;：GC 时应用线程暂停的时间。越短越好。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;内存占用（Footprint）&lt;/strong&gt;：GC 额外消耗的内存（如 G1 的 RSet、ZGC 的染色指针）。越少越好。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这三者不可能同时优化——任何 GC 都在三者间做取舍。&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-serial-gc&#34;&gt;1. Serial GC&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：单线程，回收时全部 STW&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么存在&lt;/strong&gt;：单核 CPU 或小型应用场景，多线程反而有额外开销&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;新生代：复制算法（Copying）&lt;/li&gt;&#xA;&lt;li&gt;老年代：标记-整理算法（Mark-Compact）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：客户端应用、小型服务端、单核环境&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;参数&lt;/strong&gt;：&lt;code&gt;-XX:+UseSerialGC&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;何时选它&lt;/strong&gt;：堆小于 100MB、单核 CPU。其他情况不推荐。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2-parallel-gcthroughput-gc&#34;&gt;2. Parallel GC（Throughput GC）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：多线程，目标是最大化吞吐量，但 STW 时间较长&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;设计目标&lt;/strong&gt;：&amp;ldquo;只要暂停时间在可接受范围内，吞吐量越高越好&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;新生代：复制算法（多线程）&lt;/li&gt;&#xA;&lt;li&gt;老年代：标记-整理算法（多线程）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：多核 CPU、对延迟要求不高的批处理/数据分析任务&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重要参数&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseParallelGC&lt;/code&gt;：启用&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:ParallelGCThreads&lt;/code&gt;：并行 GC 线程数（默认 = CPU 核心数）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:MaxGCPauseMillis&lt;/code&gt;：期望最大暂停时间（不是硬保证，默认无）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:GCTimeRatio&lt;/code&gt;：吞吐量目标（默认 99，即允许 1% 时间花在 GC 上）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3-cms-gcconcurrent-mark-sweep&#34;&gt;3. CMS GC（Concurrent Mark Sweep）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：并发收集老年代，尽量减少 STW 时间&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么选 CMS&lt;/strong&gt;：对于 Web 服务等延迟敏感应用，每次 Full GC 暂停几秒钟不可接受。CMS 让大部分 GC 工作与应用线程并发。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;初始标记（STW）&lt;/strong&gt;：标记 GC Roots 直接关联的对象——&lt;strong&gt;快速&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发标记&lt;/strong&gt;：从 GC Roots 开始遍历所有引用——&lt;strong&gt;与应用并发&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重新标记（STW）&lt;/strong&gt;：修正并发标记期间引用变化导致的漏标——&lt;strong&gt;较快&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发清除&lt;/strong&gt;：清除不可达对象——&lt;strong&gt;与应用并发&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;核心问题&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;内存碎片&lt;/strong&gt;：使用标记-清除算法，老年代越来越碎片化 → 最终触发 Full GC 且无法避免长时间 STW&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;CPU 敏感&lt;/strong&gt;：并发阶段抢占 CPU，应用吞吐量下降&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;浮动垃圾&lt;/strong&gt;：并发标记期间新产生的垃圾本次无法回收&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Promotion Failed&lt;/strong&gt;：新生代对象晋升老年代时无连续空间 → Full GC&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重要参数&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseConcMarkSweepGC&lt;/code&gt;：启用（JDK 9 后已废弃，JDK 14 移除）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:CMSInitiatingOccupancyFraction&lt;/code&gt;：触发 CMS 的老年代使用率阈值（默认 68%）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseCMSCompactAtFullCollection&lt;/code&gt;：Full GC 时整理内存&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:CMSFullGCsBeforeCompaction&lt;/code&gt;：多少次 Full GC 后进行一次整理&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么被废弃&lt;/strong&gt;：G1 在延迟和吞吐量之间的平衡表现更好，且 CMS 无法解决碎片化和浮动垃圾问题。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;4-g1-gcgarbage-first&#34;&gt;4. G1 GC（Garbage First）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：面向大堆、多核的服务端 GC。将堆划分为多个 Region，优先回收垃圾最多的 Region（&amp;ldquo;Garbage First&amp;rdquo; 名字的由来）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;设计思路&lt;/strong&gt;：不要求一次回收整个堆，而是分批次回收每个 Region，通过可预测的 pause time 模型控制停顿&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;初始标记(STW) → 并发标记 → 最终标记(STW) → 筛选回收(STW)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;初始标记&lt;/strong&gt;：标记 GC Roots + 修改 TAMS（Next Top at Mark Start）指针&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;并发标记&lt;/strong&gt;：从 GC Roots 遍历所有对象，记录引用变更到 SATB（Snapshot At The Beginning）队列&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;最终标记&lt;/strong&gt;：处理 SATB 队列中的漏标对象&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;筛选回收&lt;/strong&gt;：计算每个 Region 的回收价值（回收能释放多少空间 × 回收耗时），优先回收&amp;quot;垃圾最多、回收最快&amp;quot;的 Region&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;关键内部机制&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;table&gt;&#xA;&#x9;&lt;thead&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;机制&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;作用&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/thead&gt;&#xA;&#x9;&lt;tbody&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;strong&gt;Region&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;堆划分为 1MB~32MB 的 Region，每个 Region 可扮演 Eden/Survivor/Old/Humongous&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;strong&gt;RSet（Remembered Set）&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;记录其他 Region 对本 Region 的引用——避免全堆扫描&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;strong&gt;SATB（Snapshot At The Beginning）&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;并发标记开始时拍堆快照，所有在标记期间变更的引用都记录到 SATB 队列&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;strong&gt;写屏障&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;对象引用变更时触发，更新 RSet + 记录 SATB&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：堆大小 4GB+，多核 CPU，延迟要求 100-300ms&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;重要参数&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseG1GC&lt;/code&gt;：启用（JDK 9+ 默认）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:MaxGCPauseMillis&lt;/code&gt;：期望暂停时间目标（默认 200ms，G1 会努力但无法硬保证）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:G1HeapRegionSize&lt;/code&gt;：Region 大小（默认堆/2048，1~32MB）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:InitiatingHeapOccupancyPercent&lt;/code&gt;：触发并发标记的堆使用率（默认 45%）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:G1NewSizePercent&lt;/code&gt;：新生代最小占比（默认 5%）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:G1MaxNewSizePercent&lt;/code&gt;：新生代最大占比（默认 60%）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;何时选 G1&lt;/strong&gt;：JDK 11+、堆 4GB+、延迟要求几百毫秒，G1 是默认选择。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;5-zgcz-garbage-collector&#34;&gt;5. ZGC（Z Garbage Collector）&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：极低延迟（STW &amp;lt; 10ms），与堆大小基本无关（即使是 TB 级堆）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;为什么能这么低延迟&lt;/strong&gt;：几乎所有阶段都并发，只在极少数点 STW（且 STW 阶段不随堆大小增长）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;关键技术&lt;/strong&gt;：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;table&gt;&#xA;&#x9;&lt;thead&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;技术&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;作用&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/thead&gt;&#xA;&#x9;&lt;tbody&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;strong&gt;染色指针（Colored Pointers）&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;在 64 位指针的高位（42 位之后）存储 GC 状态信息（Finalizable/Remapped/Mark1/Mark0），无需额外内存&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;strong&gt;读屏障（Load Barrier）&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;每次从堆读取引用时检查指针颜色，如果对象被移动，读屏障在返回前修正引用&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;strong&gt;并发迁移（Relocation）&lt;/strong&gt;&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;存活对象在应用运行时被迁移到新区域，旧区域清空后回收&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发标记（Concurrent Mark）&lt;/strong&gt;：遍历对象图，标记存活对象。与 G1 不同，ZGC 的标记完全并发（初始标记的 STW 极短）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发迁移预备（Concurrent Prepare for Relocation）&lt;/strong&gt;：确定需要清理的 Region。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发迁移（Concurrent Relocate）&lt;/strong&gt;：将存活对象复制到新 Region，更新引用。读屏障确保应用线程始终访问到正确地址。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;并发重映射（Concurrent Remap）&lt;/strong&gt;：修正所有指向旧位置的引用。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：TB 级堆、延迟要求 &amp;lt; 10ms 的金融交易/实时系统&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;重要参数&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseZGC&lt;/code&gt;：启用（JDK 11 实验性，JDK 15 正式，JDK 18+ 默认）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:ZAllocationSpikeTolerance&lt;/code&gt;：分配尖峰容忍度（默认 2.0）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:ZCollectionInterval&lt;/code&gt;：最大回收间隔（秒）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;：ZGC 的吞吐量略低于 G1（因为读屏障开销），内存占用也更高。选 ZGC 时确认你能接受这些 Trade-off。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;6-shenandoah-gc&#34;&gt;6. Shenandoah GC&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：与 ZGC 类似，目标是极低延迟。与 ZGC 的区别在于实现方式：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;ZGC 使用染色指针（需要 64 位系统 + 特定 CPU 特性）&lt;/li&gt;&#xA;&lt;li&gt;Shenandoah 使用 Brooks 指针（对象头中加一个转发指针），不依赖硬件&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;回收流程&lt;/strong&gt;：并发标记 → 并发转移 → 并发更新引用（比 ZGC 多一个并发更新引用阶段）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：与 ZGC 类似，但不要求特定硬件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重要参数&lt;/strong&gt;：&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:+UseShenandoahGC&lt;/code&gt;：启用（JDK 12+，OpenJDK 发行版不默认包含——需要 Build 时开启）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-XX:ShenandoahGCHeuristics&lt;/code&gt;：启发式策略（adaptive/static/compact/aggressive）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;三gc-选择决策树&#34;&gt;三、GC 选择决策树&#xA;&lt;/h2&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;应用需要什么？&#xA;├─ 批处理/数据分析 → Parallel（要吞吐量）&#xA;├─ Web 服务/微服务&#xA;│  ├─ 堆 &amp;lt; 4GB → G1 或 Parallel&#xA;│  ├─ 堆 4~16GB → G1（JDK 11+ 默认）&#xA;│  ├─ 堆 &amp;gt; 16GB + 延迟敏感 → G1（延迟要求 &amp;lt; 100ms？）&#xA;│  │  └─ 是 → ZGC（JDK 17+）&#xA;│  └─ 堆 &amp;gt; 100GB + 极致低延迟 → ZGC&#xA;└─ 客户端/小型应用 → Serial&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;四gc-优化实践&#34;&gt;四、GC 优化实践&#xA;&lt;/h2&gt;&lt;h3 id=&#34;基础三步&#34;&gt;基础三步&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;确定目标&lt;/strong&gt;：是提高吞吐量还是降低延迟？&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;收集数据&lt;/strong&gt;：PrintGCDetails + GCViewer/GCEasy 分析 GC 日志&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;调整参数&lt;/strong&gt;：一次只改一个参数，观察效果&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;常用-jvm-参数组合&#34;&gt;常用 JVM 参数组合&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 打印 GC 日志（JDK 9+）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-Xlog:gc*&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-Xlog:gc:gc.log&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 打印 GC 日志（JDK 8）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# G1 生产环境常用参数&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:+UseG1GC -XX:MaxGCPauseMillis&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt; -XX:+PrintGCDetails&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 大堆 ZGC 常用参数&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-XX:+UseZGC -Xms64G -Xmx64G -XX:ZAllocationSpikeTolerance&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;2.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;内存泄漏排查思路&#34;&gt;内存泄漏排查思路&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;Heap Dump + MAT（Memory Analyzer Tool）分析大对象&lt;/li&gt;&#xA;&lt;li&gt;GC 日志中 &lt;code&gt;Full GC&lt;/code&gt; 频率异常 → 确认是否为晋升失败或 MetaSpace 泄漏&lt;/li&gt;&#xA;&lt;li&gt;Native Memory Tracking（NMT）检查 off-heap 内存&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五跨代引用与-rset-详解&#34;&gt;五、跨代引用与 RSet 详解&#xA;&lt;/h2&gt;&lt;h3 id=&#34;g1-的-rsetremembered-set&#34;&gt;G1 的 RSet（Remembered Set）&#xA;&lt;/h3&gt;&lt;p&gt;每个 Region 维护一个 RSet，记录其他 Region 对它的引用。为什么需要 RSet？Young GC 时只扫描新生代 Region，但老年代可能有对象引用新生代对象——有了 RSet 就不必全堆扫描。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;RSet 的结构&lt;/strong&gt;：哈希表，key 是来源 Region 地址，value 是来源 Region 中的卡页索引（Card Index）。卡页默认 512 字节。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;写屏障维护 RSet&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;writeBarrier&lt;/span&gt;(Field field, Object newObj) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Object oldObj &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; field.&lt;span style=&#34;color:#a6e22e&#34;&gt;get&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (oldObj &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; isCrossRegionRef(oldObj, newObj)) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        addToRSet(oldObj.&lt;span style=&#34;color:#a6e22e&#34;&gt;region&lt;/span&gt;(), newObj.&lt;span style=&#34;color:#a6e22e&#34;&gt;region&lt;/span&gt;(), getCardIndex(oldObj));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    field.&lt;span style=&#34;color:#a6e22e&#34;&gt;set&lt;/span&gt;(newObj);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;g1-vs-cms-跨代引用处理对比&#34;&gt;G1 vs CMS 跨代引用处理对比&#xA;&lt;/h3&gt;&lt;table&gt;&#xA;&#x9;&lt;thead&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;机制&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;G1&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;CMS&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/thead&gt;&#xA;&#x9;&lt;tbody&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;跨代引用处理&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;每个 Region 维护 RSet&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;全局卡表（Card Table）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;精度&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;精确到 Region + 卡页&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;粗粒度（卡表页）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;内存开销&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;较高（每个 Region 一个 RSet）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;较低（全局卡表）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;扫描效率&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;仅扫描相关 Region&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;需扫描整个老年代脏卡页&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;</description>
        </item></channel>
</rss>
