<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>JVM on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/jvm/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Tue, 03 Mar 2026 10:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/jvm/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>Netflix 用 JDK Vector API 优化推荐系统：一次教科书级的性能工程实录</title>
      <link>https://ftmao.com/blog/posts/netflix-jdk-vector-api-recommendation/</link>
      <pubDate>Tue, 03 Mar 2026 10:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/netflix-jdk-vector-api-recommendation/</guid>
      <description>&lt;h1 id=&#34;netflix-用-jdk-vector-api-优化推荐系统一次教科书级的性能工程实录&#34;&gt;Netflix 用 JDK Vector API 优化推荐系统：一次教科书级的性能工程实录&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;原文：&lt;a href=&#34;https://netflixtechblog.com/optimizing-recommendation-systems-with-jdks-vector-api-30d2830401ec&#34;&gt;Optimizing Recommendation Systems with JDK&amp;rsquo;s Vector API&lt;/a&gt;
目标读者：写 Java 后端、关心 JVM 性能工程的工程师；也适合任何在“要不要引入原生库/SIMD”上纠结过的人。
阅读目标：看清一次完整性能优化的正确顺序——先改计算形状，再改数据布局，最后才轮到换计算内核。以及理解为什么 BLAS 这种“标准答案”在真实生产路径里会失效。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一背景ranker-里的-75-热点&#34;&gt;一、背景：Ranker 里的 7.5% 热点&lt;/h2&gt;
&lt;p&gt;Ranker 是 Netflix 最大、最复杂的服务之一，首页那些个性化推荐行就是它算出来的。看 CPU profile 时有一个特征始终扎眼：&lt;strong&gt;视频惊喜度打分（video serendipity scoring）&lt;/strong&gt;——回答一个简单问题：“这部新片和你最近看的东西有多不一样？”这个特征吃掉每个节点约 &lt;strong&gt;7.5% 的总 CPU&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;算法本身不复杂：候选视频和用户历史里的每个视频都表示成 embedding 向量；对每个候选，算出它与所有历史向量的余弦相似度，取最大值，用 1 减去它得到“新颖度”分数，作为下游推荐逻辑的输入特征。原始实现非常直白：对每个候选取 embedding，遍历历史逐对算余弦，维护最大值。容易理解，但在 Ranker 的规模下意味着大量串行工作、重复查找、分散的内存访问和糟糕的缓存局部性。火焰图确认了这一点：服务里最热的热点之一就是惊喜度编码器里的 Java 点积。算法层面，这是一个 &lt;strong&gt;M 个候选 × N 个历史&lt;/strong&gt;的嵌套循环，产生 O(M×N) 次独立点积。&lt;/p&gt;
&lt;p&gt;一个容易被忽略但决定了整个优化方向的数据：他们埋点统计了流量形状，发现&lt;strong&gt;约 98% 的请求是单视频请求，剩下 2% 是大批量请求&lt;/strong&gt;——但那 2% 的批次实在太大，最终处理的视频总量在单视频和批处理之间大约是 &lt;strong&gt;50:50&lt;/strong&gt;。所以批处理值得做，即使它对中位数请求毫无帮助。&lt;/p&gt;
&lt;h2 id=&#34;二第一步把嵌套循环看成矩阵乘&#34;&gt;二、第一步：把嵌套循环看成矩阵乘&lt;/h2&gt;
&lt;p&gt;第一个想法是换“计算形状”：不再想成“很多次小点积”，而是当成一次矩阵运算。设 embedding 维度为 D：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;把所有候选 embedding 装进矩阵 A（形状 M×D）；&lt;/li&gt;
&lt;li&gt;把所有历史 embedding 装进矩阵 B（形状 N×D）；&lt;/li&gt;
&lt;li&gt;所有行归一化成单位向量；&lt;/li&gt;
&lt;li&gt;计算 &lt;code&gt;C = A × Bᵀ&lt;/code&gt;，C 就是 M×N 的余弦相似度矩阵。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这样 &lt;strong&gt;M×N 次独立点积变成一次矩阵乘&lt;/strong&gt;——而这正是 CPU 和优化过的计算内核最擅长的东西。工程上通过同时支持 &lt;code&gt;encode()&lt;/code&gt;（单视频）和 &lt;code&gt;batchEncode()&lt;/code&gt;（批量）接入现有框架，保持向后兼容。到这里看起来像“做完了”。但并没有。&lt;/p&gt;
&lt;h2 id=&#34;三第二步批处理反而慢了-5&#34;&gt;三、第二步：批处理反而慢了 5%&lt;/h2&gt;
&lt;p&gt;上了批处理版本跑金丝雀，结果出人意料：&lt;strong&gt;性能回退约 5%&lt;/strong&gt;。算法没问题——把点积归并成矩阵乘在数学上是等价的。问题出在第一版实现自己引入的开销：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;每个批次都新建 &lt;code&gt;double[][]&lt;/code&gt; 矩阵装候选、历史和结果。这些又大又短命的对象制造了 GC 压力；而且 &lt;code&gt;double[][]&lt;/code&gt; 在内存里本身就不连续，多一层指针跳转，缓存行为更差。&lt;/li&gt;
&lt;li&gt;第一版 Java 矩阵乘是朴素的标量实现，用不上 SIMD。换句话说，&lt;strong&gt;付了批处理的成本，却没拿到批处理该有的计算效率&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;教训来得很快：算法层面的改进，如果实现细节——内存布局、分配策略、计算内核——跟你作对，就一文不值。这一步定下了后面的路线：先把数据布局改成缓存友好的，消灭每批次分配，然后再回头解决矩阵乘内核。&lt;/p&gt;
&lt;h2 id=&#34;四第三步扁平-buffer-加-threadlocal-复用&#34;&gt;四、第三步：扁平 buffer 加 ThreadLocal 复用&lt;/h2&gt;
&lt;p&gt;重做数据布局。&lt;code&gt;double[m][n]&lt;/code&gt; 换成&lt;strong&gt;行主序的扁平 &lt;code&gt;double[]&lt;/code&gt;&lt;/strong&gt;：内存连续，访问模式可预测。然后引入 &lt;code&gt;ThreadLocal&amp;lt;BufferHolder&amp;gt;&lt;/code&gt;，持有候选、历史等可复用 buffer——&lt;strong&gt;buffer 只增长不收缩&lt;/strong&gt;，避免每请求分配，同时每个线程持有自己的一份，无锁无争用。核心逻辑就几行：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;class BufferHolder {
  double[] candidatesFlat = new double[0];
  double[] getCandidatesFlat(int required) {
    if (candidatesFlat.length &amp;lt; required) {
      candidatesFlat = new double[required];
    }
    return candidatesFlat;
  }
  // historyFlat 同理
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;光是这一步，批处理路径就变得可预测多了：分配少了，GC 压力小了，缓存局部性好了。剩下的问题回到最初的那个：矩阵乘到底用什么算？&lt;/p&gt;
&lt;h2 id=&#34;五第四步blas测试里很好生产里不行&#34;&gt;五、第四步：BLAS——测试里很好，生产里不行&lt;/h2&gt;
&lt;p&gt;显而易见的下一步是 BLAS（Basic Linear Algebra Subprograms）。隔离的微基准看起来很有希望，但一旦接进真实的批量打分路径，收益就没兑现。几个因素在作对：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;默认的 &lt;code&gt;netlib-java&lt;/code&gt; 路径走的是 F2J（Fortran 转 Java）的 BLAS，不是真正的原生实现；&lt;/li&gt;
&lt;li&gt;就算用原生 BLAS，也要付 setup 和 JNI 边界切换的开销；&lt;/li&gt;
&lt;li&gt;Java 的行主序和很多 BLAS 例程期望的列主序对不上，会引入转换和临时 buffer；&lt;/li&gt;
&lt;li&gt;这些额外的分配和拷贝在完整流水线里很扎眼，尤其是旁边还有 TensorFlow 的 embedding 计算。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;BLAS 不是白试——它帮忙看清了时间到底花在哪。但它不是那种即插即用的胜利。他们需要的是：&lt;strong&gt;纯 Java、贴合扁平 buffer 架构、还能用上 SIMD&lt;/strong&gt; 的东西。&lt;/p&gt;
&lt;h2 id=&#34;六第五步jdk-vector-api&#34;&gt;六、第五步：JDK Vector API&lt;/h2&gt;
&lt;h3 id=&#34;先补一课jdk-vector-api-到底是什么&#34;&gt;先补一课：JDK Vector API 到底是什么&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;起点是 SIMD。&lt;/strong&gt; 现代 x86 CPU 都有向量寄存器，一条指令可以同时算多个数：AVX2 的 256 位寄存器一次装 4 个 double，AVX-512 的 512 位一次装 8 个。一条向量乘加指令顶 4-8 条标量指令——这就是 SIMD（Single Instruction, Multiple Data，单指令多数据），点积、矩阵乘这类规则的数值计算是它的主场。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Java 的痛点是：这些指令一直在硬件里，Java 程序员却够不着。&lt;/strong&gt; JIT 有自动向量化，但只对形状简单、能被它证明安全的循环生效，代码稍微复杂一点就悄悄退回标量，而且没有任何方式强制它发生；想要确定性的 SIMD，只能走 JNI 调原生库——代价就是上一步 BLAS 踩过的那些坑。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vector API 是 Project Panama 的一部分&lt;/strong&gt;，从 JDK 16 起以孵化模块 &lt;code&gt;jdk.incubator.vector&lt;/code&gt; 的形式提供，到原文写作时仍在孵化（所以运行时要显式 &lt;code&gt;--add-modules&lt;/code&gt;）。它把 SIMD 变成了普通 Java 代码：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;VectorSpecies&lt;/code&gt; 描述「一次算几个 lane」（lane 就是向量寄存器里的一个槽位），&lt;code&gt;SPECIES_PREFERRED&lt;/code&gt; 让运行时按当前 CPU 挑最优宽度；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DoubleVector.fromArray(...)&lt;/code&gt; 从数组加载一组 lane，&lt;code&gt;fma(b, acc)&lt;/code&gt; 做向量融合乘加，&lt;code&gt;reduceLanes(ADD)&lt;/code&gt; 把各 lane 归约成一个标量；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;同一份代码的可移植性由 JIT 兜底&lt;/strong&gt;：编译时映射到宿主机器最好的指令集，AVX-512 机器跑 8 lane，AVX2 机器跑 4 lane，都不支持就退回标量。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    subgraph S[&amp;#34;标量路径 一条指令算一个数&amp;#34;]
        A1[&amp;#34;a0 乘 b0&amp;#34;] --&amp;gt; R1[&amp;#34;acc 逐个累加&amp;#34;]
        A2[&amp;#34;a1 乘 b1&amp;#34;] --&amp;gt; R1
        A3[&amp;#34;a2 乘 b2&amp;#34;] --&amp;gt; R1
        A4[&amp;#34;a3 乘 b3&amp;#34;] --&amp;gt; R1
    end
    subgraph V[&amp;#34;SIMD 路径 AVX2 一条指令算四个数&amp;#34;]
        B1[&amp;#34;向量寄存器加载&amp;lt;br/&amp;gt;a0 a1 a2 a3&amp;#34;] --&amp;gt; F[&amp;#34;一条 fma 指令&amp;#34;]
        B2[&amp;#34;向量寄存器加载&amp;lt;br/&amp;gt;b0 b1 b2 b3&amp;#34;] --&amp;gt; F
        F --&amp;gt; R2[&amp;#34;acc 四个 lane 同时累加&amp;#34;]
    end
    style F fill:#e8f5e9&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;一句话总结：&lt;strong&gt;它把「手写 intrinsics 的活」变成了「写普通循环的活」&lt;/strong&gt;——你不用知道目标机器是 SSE 还是 AVX-512，JIT 替你选。对他们来说更关键的是：&lt;strong&gt;纯 Java，没有原生依赖，没有 JNI 切换，写起来就是普通 Java 代码&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;跟他们的负载是绝配：embedding 已经搬进了扁平连续的 &lt;code&gt;double[]&lt;/code&gt; buffer，热循环被海量点积占满。最后一步就是用基于 Vector API 的纯 Java SIMD 实现换掉 BLAS——藏在一个小工厂后面，类加载时由 &lt;code&gt;MatMulFactory&lt;/code&gt; 选最优实现：&lt;code&gt;jdk.incubator.vector&lt;/code&gt; 可用就用 Vector API，否则退回一个高度优化的标量实现——循环展开的点积（同事 Patrick Strawderman 实现，灵感来自 Lucene 里的模式）。&lt;/p&gt;
&lt;p&gt;Vector API 版本的内层循环：用 &lt;code&gt;fma()&lt;/code&gt;（fused multiply-add）把 &lt;code&gt;a * b&lt;/code&gt; 累加进向量累加器；&lt;code&gt;DoubleVector.SPECIES_PREFERRED&lt;/code&gt; 让运行时自己挑适合机器的 lane 宽度（AVX2 上通常 4 个 double，AVX-512 上 8 个）。简化版：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;for (int i = 0; i &amp;lt; M; i++) {
  for (int j = 0; j &amp;lt; N; j++) {
    DoubleVector acc = DoubleVector.zero(SPECIES);
    int k = 0;
    for (; k + SPECIES.length() &amp;lt;= D; k += SPECIES.length()) {
      DoubleVector a = DoubleVector.fromArray(SPECIES, candidatesFlat, i*D + k);
      DoubleVector b = DoubleVector.fromArray(SPECIES, historyFlat, j*D + k);
      acc = a.fma(b, acc);  // 融合乘加
    }
    double dot = acc.reduceLanes(VectorOperators.ADD);
    // 处理 k..D-1 的尾部
    similaritiesFlat[i*N + j] = dot;
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;原来的一长串标量乘加，变成少量向量 &lt;code&gt;fma()&lt;/code&gt; 加一次归约——算法没变，CPU 向量单元的利用率完全不同。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    subgraph OLD[&amp;#34;原始路径 标量&amp;#34;]
        O1[&amp;#34;候选 embedding&amp;#34;] --&amp;gt; O3[&amp;#34;逐个算余弦相似度&amp;#34;]
        O2[&amp;#34;历史 embedding 逐个取&amp;#34;] --&amp;gt; O3
        O3 --&amp;gt; O4[&amp;#34;M 乘 N 次独立点积&amp;lt;br/&amp;gt;分散内存访问 缓存不友好&amp;#34;]
    end
    subgraph NEW[&amp;#34;优化后路径 SIMD&amp;#34;]
        N1[&amp;#34;候选装入扁平 buffer A&amp;lt;br/&amp;gt;M×D 行主序&amp;#34;] --&amp;gt; N3[&amp;#34;归一化为单位向量&amp;#34;]
        N2[&amp;#34;历史装入扁平 buffer B&amp;lt;br/&amp;gt;N×D 行主序&amp;#34;] --&amp;gt; N3
        N3 --&amp;gt; N4[&amp;#34;一次矩阵乘 C = A × Bᵀ&amp;lt;br/&amp;gt;Vector API fma 累加&amp;#34;]
        N4 --&amp;gt; N5[&amp;#34;每行取最大值&amp;lt;br/&amp;gt;novelty = 1 - maxSim&amp;#34;]
    end
    O4 -.-&amp;gt;|&amp;#34;重构计算形状&amp;#34;| N1
    style O4 fill:#ffcccc
    style N4 fill:#e8f5e9&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h2 id=&#34;七回退与安全孵化特性的生产姿势&#34;&gt;七、回退与安全：孵化特性的生产姿势&lt;/h2&gt;
&lt;p&gt;Vector API 还在孵化，运行时要加 &lt;code&gt;--add-modules=jdk.incubator.vector&lt;/code&gt; 才能用。他们不想让正确性和可用性绑在这个 flag 上，所以把回退行为显式设计出来：启动时探测 Vector API 支持，有就走 SIMD 批量矩阵乘，没有就走优化过的标量路径，单视频请求继续用逐条实现。运营故事很干净：服务可以选择启用 Vector API 拿满性能，不启用系统也照样安全可预测。&lt;/p&gt;
&lt;h2 id=&#34;八生产结果&#34;&gt;八、生产结果&lt;/h2&gt;
&lt;p&gt;完整方案（批处理 + 扁平 buffer + ThreadLocal 复用 + Vector API）在跑生产流量的金丝雀上测得：&lt;strong&gt;CPU 利用率下降约 7%，平均延迟下降约 12%&lt;/strong&gt;；为了归一化吞吐差异还跟踪了 CPU/RPS（每 RPS 消耗的 CPU），&lt;strong&gt;改善约 10%&lt;/strong&gt;——同样的流量可以少用约 10% 的 CPU，全量上线后数据保持住了。在函数级别，这个特征占的 CPU 从最初的 &lt;strong&gt;7.5% 降到约 1%&lt;/strong&gt;。汇编层面的变化也很直白：从循环展开的标量点积，变成 AVX-512 硬件上的向量化矩阵乘。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;工程实践联想&#34;&gt;工程实践联想&lt;/h2&gt;
&lt;p&gt;这篇文章值得读两遍：第一遍看技术，第二遍看顺序。沉淀下来的启示：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;优化顺序是：计算形状 → 数据布局 → 分配策略 → 计算内核。&lt;/strong&gt; 他们最后换的才是内核（Vector API），但前面三步缺任何一步，换内核都拿不到收益。那个 5% 的回退也说明：跳过布局直接批处理，等于同时引入新开销和新瓶颈。做性能优化先问“形状对不对”，再问“数据在内存里躺得对不对”，最后才轮到“用什么算”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;微基准通过不等于生产有效。&lt;/strong&gt; BLAS 在隔离测试里很有希望，一进真实路径就被 JNI、布局转换、临时分配吃光收益。任何库的 benchmark 都只对它自己的测试负责；决策必须在真实流量路径里做，最好带着上下游（他们旁边还跑着 TensorFlow 的 embedding 计算）一起测。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;double[][]&lt;/code&gt; 到扁平 &lt;code&gt;double[]&lt;/code&gt; 是 Java 性能工程的经典动作。&lt;/strong&gt; 二维数组是“数组的数组”，行指针分散，缓存局部性差；扁平数组行主序连续、访问可预测，配合 ThreadLocal buffer 只增不缩，每请求分配降成零——这套组合在 Lucene、Netty 里到处都是，值得变成肌肉记忆。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流量形状决定优化对象。&lt;/strong&gt; 98% 的请求是单视频，只看中位数的话批处理毫无价值；但那 2% 的大批量扛了一半总计算量。看 p50 优化和看总量优化是两个问题，先埋点搞清楚自己的流量长什么样。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;孵化/预览特性的正确姿势：工厂加探测加回退。&lt;/strong&gt; 不赌 &lt;code&gt;--add-modules&lt;/code&gt; 一定加得上，启动时探测、随时退回标量实现，“试用新 JDK 特性”就从一次豪赌变成一个配置项。这个模式可以复用到任何“新能力可用性不确定”的场景。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;顺带一个私货：这篇文章最好的地方是诚实——它把“我们以为做完了结果慢了 5%”和“BLAS 没成”都写了出来。性能工程的真实过程就是这样：每一步的正确性都要靠金丝雀和生产数据确认，不存在一步到位。那些只写成功结果的优化文章，参考价值反而低。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;本篇小结&#34;&gt;本篇小结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;问题&lt;/strong&gt;：Netflix Ranker 的视频惊喜度打分（候选与历史 embedding 的余弦相似度取 max）占单节点 CPU 约 7.5%，热点是 O(M×N) 的逐对点积；流量形状 98% 单视频、2% 大批量，但计算总量 50:50。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;路径&lt;/strong&gt;：M×N 次点积重构成矩阵乘 &lt;code&gt;C = A × Bᵀ&lt;/code&gt;（行归一化后即余弦相似度矩阵）→ 金丝雀回退约 5%（&lt;code&gt;double[][]&lt;/code&gt; 分配与 GC、非连续布局、标量内核）→ 扁平 &lt;code&gt;double[]&lt;/code&gt; 行主序加 &lt;code&gt;ThreadLocal&amp;lt;BufferHolder&amp;gt;&lt;/code&gt; 复用（buffer 只增不缩）→ BLAS 因 F2J 非原生、JNI 开销、行列主序不匹配而放弃 → 终解 JDK Vector API（&lt;code&gt;fma()&lt;/code&gt; 累加、&lt;code&gt;SPECIES_PREFERRED&lt;/code&gt; 自适应 lane 宽度、JIT 映射 SSE/AVX2/AVX-512）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;安全姿势&lt;/strong&gt;：&lt;code&gt;MatMulFactory&lt;/code&gt; 启动时探测，不可用则回退到 Lucene 风格的循环展开标量实现，不依赖 &lt;code&gt;--add-modules&lt;/code&gt; 一定在场。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生产结果&lt;/strong&gt;：CPU 降约 7%、平均延迟降约 12%、CPU/RPS 改善约 10%、该特征的函数级 CPU 占比从 7.5% 降到约 1%；汇编从标量循环展开点积变成 AVX-512 向量化矩阵乘。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;核心结论&lt;/strong&gt;：优化拼的不是“最快的库”，而是把计算形状、内存布局、分配策略这些基本功做对——这些就位之后，Vector API 才成为那个“顺其自然的选择”。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://netflixtechblog.com/optimizing-recommendation-systems-with-jdks-vector-api-30d2830401ec&#34;&gt;Optimizing Recommendation Systems with JDK&amp;rsquo;s Vector API — Netflix Technology Blog&lt;/a&gt;（原文，作者 Harshad Sane，2026-03-03）&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/338&#34;&gt;JEP 338: Vector API (Incubator) — OpenJDK&lt;/a&gt;（Vector API 的 JEP 入口，含 SPECIES、fma、lane 等概念定义；后续孵化迭代见 JEP 417/426/448/460）&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/fommil/netlib-java&#34;&gt;netlib-java — GitHub&lt;/a&gt;（文中提到的 Java BLAS 库，默认 F2J 路径的出处）&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lucene.apache.org/&#34;&gt;Apache Lucene&lt;/a&gt;（回退路径标量点积实现的灵感来源，Lucene 在向量检索里大量使用循环展开和 Panama Vector API）&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    <item>
      <title>JVM 内功修炼：运行时数据区、GC 演进与现代调优实践</title>
      <link>https://ftmao.com/blog/posts/jvm-internals-guide/</link>
      <pubDate>Wed, 28 Mar 2018 14:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/jvm-internals-guide/</guid>
      <description>&lt;h1 id=&#34;jvm-内功修炼运行时数据区gc-演进与现代调优实践&#34;&gt;JVM 内功修炼：运行时数据区、GC 演进与现代调优实践&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;JVM 是 Java 程序员逃不掉的「操作系统」。懂它不是为了背八股，而是为了在 OOM、Full GC、CPU 飙升时，能一眼定位根因并给出调优方案。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一高层次思想jvm-在帮你解决什么问题&#34;&gt;一、高层次思想：JVM 在帮你解决什么问题？&lt;/h2&gt;
&lt;p&gt;JVM 的核心职责可以抽象成三件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;一次编译，到处运行&lt;/strong&gt;：通过字节码 + 解释/编译执行，屏蔽底层 OS 与硬件差异。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动内存管理&lt;/strong&gt;：让开发者专注于业务，而不是像 C/C++ 那样手动 malloc/free。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;运行时优化&lt;/strong&gt;：JIT 编译、逃逸分析、内联、锁消除等，把「解释执行」慢慢优化成「本地机器码执行」。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[.java 源码] --&amp;gt;|javac| B[字节码 .class]
    B --&amp;gt;|类加载子系统| C[方法区/Metaspace]
    C --&amp;gt;|解释器| D[逐行解释执行]
    C --&amp;gt;|JIT 编译器| E[本地机器码]
    D --&amp;gt; F[执行引擎]
    E --&amp;gt; F
    F --&amp;gt; G[操作系统]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #1&lt;/strong&gt;：不要只把 JVM 当「黑盒」。线上 90% 的 Java 性能问题，根源都在堆外内存泄漏、GC 停顿过长、Metaspace 膨胀、线程栈溢出这四类。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二运行时数据区新版-jdk-的版图&#34;&gt;二、运行时数据区：新版 JDK 的版图&lt;/h2&gt;
&lt;p&gt;不同虚拟机的运行时数据区实现略有差异，但都遵循《Java 虚拟机规范》。现代视角下，区域可划分为「线程私有」和「线程共享」两类：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    subgraph 线程私有
        A[程序计数器 PC Register]
        B[虚拟机栈 JVM Stack]
        C[本地方法栈 Native Method Stack]
    end
    subgraph 线程共享
        D[堆 Heap]
        E[方法区 Method Area / Metaspace]
        F[直接内存 Direct Memory]
    end
    A --&amp;gt; G[线程执行上下文]
    B --&amp;gt; G
    C --&amp;gt; G
    D --&amp;gt; H[几乎所有对象实例]
    E --&amp;gt; I[类元数据/常量/静态变量]
    F --&amp;gt; J[NIO / 堆外内存]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;21-程序计数器program-counter-register&#34;&gt;2.1 程序计数器（Program Counter Register）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;当前线程执行字节码的&lt;strong&gt;行号指示器&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;分支、循环、跳转、异常处理、线程恢复都依赖它。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;线程私有&lt;/strong&gt;，生命周期与线程一致。&lt;/li&gt;
&lt;li&gt;唯一一个在《Java 虚拟机规范》中&lt;strong&gt;没有规定 OOM&lt;/strong&gt; 的区域。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;22-java-虚拟机栈jvm-stack&#34;&gt;2.2 Java 虚拟机栈（JVM Stack）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;每个方法执行时创建一个&lt;strong&gt;栈帧&lt;/strong&gt;（Stack Frame）。&lt;/li&gt;
&lt;li&gt;栈帧里包含：局部变量表、操作数栈、动态链接、方法返回地址。&lt;/li&gt;
&lt;li&gt;局部变量表中的基本数据类型和对象引用在编译期大小就确定。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[JVM Stack] --&amp;gt; B[栈帧 Frame 1]
    A --&amp;gt; C[栈帧 Frame 2]
    A --&amp;gt; D[栈帧 Frame 3]
    B --&amp;gt; B1[局部变量表]
    B --&amp;gt; B2[操作数栈]
    B --&amp;gt; B3[动态链接]
    B --&amp;gt; B4[方法返回地址]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #2&lt;/strong&gt;：&lt;code&gt;-Xss&lt;/code&gt; 设置线程栈大小。递归过深、方法调用链过长会抛出 &lt;code&gt;StackOverflowError&lt;/code&gt;；如果线程创建太多，总栈空间超过限制，会抛出 &lt;code&gt;OutOfMemoryError: unable to create new native thread&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;23-本地方法栈native-method-stack&#34;&gt;2.3 本地方法栈（Native Method Stack）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;与虚拟机栈作用相同，只是为 Native 方法服务。&lt;/li&gt;
&lt;li&gt;HotSpot 中把虚拟机栈和本地方法栈合二为一了。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;24-java-堆java-heap&#34;&gt;2.4 Java 堆（Java Heap）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;JVM 管理的&lt;strong&gt;最大一块内存&lt;/strong&gt;，被所有线程共享。&lt;/li&gt;
&lt;li&gt;几乎所有对象实例和数组都在这里分配。&lt;/li&gt;
&lt;li&gt;现代 GC 基本都采用&lt;strong&gt;分代收集&lt;/strong&gt;，逻辑上分为新生代、老年代。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[Java Heap] --&amp;gt; B[Young Generation 新生代]
    A --&amp;gt; C[Old Generation 老年代]
    B --&amp;gt; D[Eden 区]
    B --&amp;gt; E[Survivor From]
    B --&amp;gt; F[Survivor To]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #3&lt;/strong&gt;：不要把「堆」和「栈」对立记忆。对象在堆里，引用在栈里；但 HotSpot 的&lt;strong&gt;逃逸分析 + 标量替换&lt;/strong&gt;会把未逃逸的小对象直接分配在栈上，减轻 GC 压力。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;25-方法区method-area与-metaspace&#34;&gt;2.5 方法区（Method Area）与 Metaspace&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;存储类信息、常量、静态变量、JIT 编译后的代码缓存。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JDK 7 之前&lt;/strong&gt;：方法区在 PermGen（永久代）中，大小固定，&lt;code&gt;-XX:MaxPermSize&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JDK 8 及以后&lt;/strong&gt;：PermGen 被移除，方法区使用本地内存中的 &lt;strong&gt;Metaspace&lt;/strong&gt;，默认只受限于系统内存，用 &lt;code&gt;-XX:MaxMetaspaceSize&lt;/code&gt; 控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;版本&lt;/th&gt;
					&lt;th&gt;实现&lt;/th&gt;
					&lt;th&gt;配置参数&lt;/th&gt;
					&lt;th&gt;常见问题&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;JDK 7-&lt;/td&gt;
					&lt;td&gt;PermGen&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-XX:PermSize&lt;/code&gt; / &lt;code&gt;-XX:MaxPermSize&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;动态生成类过多导致 &lt;code&gt;OutOfMemoryError: PermGen space&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;JDK 8+&lt;/td&gt;
					&lt;td&gt;Metaspace&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-XX:MetaspaceSize&lt;/code&gt; / &lt;code&gt;-XX:MaxMetaspaceSize&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;类加载器泄漏导致 Metaspace 持续增长&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #4&lt;/strong&gt;：Metaspace 默认无上限，服务运行久了可能把容器内存撑爆。线上建议显式设置 &lt;code&gt;-XX:MaxMetaspaceSize&lt;/code&gt;，配合监控告警。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;26-直接内存direct-memory&#34;&gt;2.6 直接内存（Direct Memory）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;不属于 JVM 堆，但会被 JVM 直接使用，常见于 NIO 的 &lt;code&gt;DirectByteBuffer&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;分配和回收成本较高，但读写 I/O 时避免了堆内外内存拷贝（Zero Copy）。&lt;/li&gt;
&lt;li&gt;默认大小约等于 &lt;code&gt;-Xmx&lt;/code&gt;，可用 &lt;code&gt;-XX:MaxDirectMemorySize&lt;/code&gt; 控制。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #5&lt;/strong&gt;：Netty、RocketMQ、Elasticsearch 等中间件大量使用堆外内存。出现 &lt;code&gt;OutOfMemoryError: Direct buffer memory&lt;/code&gt; 时，先检查是否有 &lt;code&gt;ByteBuf&lt;/code&gt; / &lt;code&gt;DirectByteBuffer&lt;/code&gt; 未释放，而不是盲目加堆内存。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三垃圾回收从算法到收集器演进&#34;&gt;三、垃圾回收：从算法到收集器演进&lt;/h2&gt;
&lt;h3 id=&#34;31-判断对象是否存活&#34;&gt;3.1 判断对象是否存活&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;引用计数法&lt;/strong&gt;：Python 用，但 Java 不用，因为解决不了循环引用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可达性分析（Reachability Analysis）&lt;/strong&gt;：从 GC Roots 出发，不可达则回收。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;常见 GC Roots：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;虚拟机栈中局部变量表引用的对象。&lt;/li&gt;
&lt;li&gt;方法区中类静态属性、常量引用的对象。&lt;/li&gt;
&lt;li&gt;本地方法栈中 JNI 引用的对象。&lt;/li&gt;
&lt;li&gt;被同步锁持有的对象。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[GC Roots] --&amp;gt; B[栈帧局部变量]
    A --&amp;gt; C[静态变量]
    A --&amp;gt; D[常量]
    A --&amp;gt; E[JNI 引用]
    A --&amp;gt; F[锁持有对象]
    B --&amp;gt; G[可达对象]
    C --&amp;gt; G
    D --&amp;gt; H[不可达对象&amp;lt;br/&amp;gt;等待回收]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;32-四种基础-gc-算法&#34;&gt;3.2 四种基础 GC 算法&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;算法&lt;/th&gt;
					&lt;th&gt;思想&lt;/th&gt;
					&lt;th&gt;优点&lt;/th&gt;
					&lt;th&gt;缺点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;标记-清除&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;标记无用对象，然后清除&lt;/td&gt;
					&lt;td&gt;简单，不需要移动对象&lt;/td&gt;
					&lt;td&gt;效率低，产生内存碎片&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;复制&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;内存分两块，活着的对象复制到另一块&lt;/td&gt;
					&lt;td&gt;无碎片，回收效率高&lt;/td&gt;
					&lt;td&gt;内存利用率只有一半&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;标记-整理&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;标记后把存活对象移到一端，清理边界外&lt;/td&gt;
					&lt;td&gt;无碎片，内存利用率高&lt;/td&gt;
					&lt;td&gt;移动对象开销大&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;分代收集&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;按对象存活周期分代，不同代用不同算法&lt;/td&gt;
					&lt;td&gt;兼顾吞吐与停顿&lt;/td&gt;
					&lt;td&gt;需要维护复杂的跨代引用&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;33-经典垃圾收集器&#34;&gt;3.3 经典垃圾收集器&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;收集器&lt;/th&gt;
					&lt;th&gt;工作区域&lt;/th&gt;
					&lt;th&gt;算法&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
					&lt;th&gt;状态&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Serial&lt;/td&gt;
					&lt;td&gt;新生代&lt;/td&gt;
					&lt;td&gt;复制&lt;/td&gt;
					&lt;td&gt;单线程，简单高效&lt;/td&gt;
					&lt;td&gt;客户端模式 / 单核&lt;/td&gt;
					&lt;td&gt;可用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ParNew&lt;/td&gt;
					&lt;td&gt;新生代&lt;/td&gt;
					&lt;td&gt;复制&lt;/td&gt;
					&lt;td&gt;Serial 的多线程版&lt;/td&gt;
					&lt;td&gt;配合 CMS&lt;/td&gt;
					&lt;td&gt;随 CMS 移除&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Parallel Scavenge&lt;/td&gt;
					&lt;td&gt;新生代&lt;/td&gt;
					&lt;td&gt;复制&lt;/td&gt;
					&lt;td&gt;吞吐量优先&lt;/td&gt;
					&lt;td&gt;后台计算&lt;/td&gt;
					&lt;td&gt;可用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Serial Old&lt;/td&gt;
					&lt;td&gt;老年代&lt;/td&gt;
					&lt;td&gt;标记-整理&lt;/td&gt;
					&lt;td&gt;单线程&lt;/td&gt;
					&lt;td&gt;客户端模式&lt;/td&gt;
					&lt;td&gt;可用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Parallel Old&lt;/td&gt;
					&lt;td&gt;老年代&lt;/td&gt;
					&lt;td&gt;标记-整理&lt;/td&gt;
					&lt;td&gt;多线程吞吐量优先&lt;/td&gt;
					&lt;td&gt;后台计算&lt;/td&gt;
					&lt;td&gt;可用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;CMS&lt;/td&gt;
					&lt;td&gt;老年代&lt;/td&gt;
					&lt;td&gt;标记-清除&lt;/td&gt;
					&lt;td&gt;低停顿，并发收集&lt;/td&gt;
					&lt;td&gt;互联网低延迟服务&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;JDK 14 已移除&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;G1&lt;/td&gt;
					&lt;td&gt;整堆&lt;/td&gt;
					&lt;td&gt;标记-整理 + 复制&lt;/td&gt;
					&lt;td&gt;可控停顿， region 化&lt;/td&gt;
					&lt;td&gt;大堆、低延迟&lt;/td&gt;
					&lt;td&gt;JDK 9-22 默认&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ZGC&lt;/td&gt;
					&lt;td&gt;整堆&lt;/td&gt;
					&lt;td&gt;标记-复制/整理&lt;/td&gt;
					&lt;td&gt;亚毫秒停顿，TB 级堆&lt;/td&gt;
					&lt;td&gt;极低延迟&lt;/td&gt;
					&lt;td&gt;JDK 23+ 默认（分代）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Shenandoah&lt;/td&gt;
					&lt;td&gt;整堆&lt;/td&gt;
					&lt;td&gt;标记-复制/整理&lt;/td&gt;
					&lt;td&gt;低停顿，独立于分代&lt;/td&gt;
					&lt;td&gt;低延迟&lt;/td&gt;
					&lt;td&gt;可用，JDK 24 实验分代&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[Serial] --&amp;gt; B[ParNew]
    B --&amp;gt; C[Parallel Scavenge]
    C --&amp;gt; D[G1]
    D --&amp;gt; E[ZGC / Shenandoah]
    style E fill:#f9f,stroke:#333&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;34-分代模型的工作流程&#34;&gt;3.4 分代模型的工作流程&lt;/h3&gt;
&lt;p&gt;新生代默认占堆的 1/3，老年代占 2/3。新生代内部 Eden:From Survivor:To Survivor 默认约为 8:1:1。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant Eden
    participant From as Survivor From
    participant To as Survivor To
    participant Old as Old Generation
    Note over Eden,Old: Minor GC 触发
    Eden-&amp;gt;&amp;gt;To: 存活对象复制到 To
    From-&amp;gt;&amp;gt;To: 存活对象复制到 To
    From-&amp;gt;&amp;gt;Old: 年龄超过阈值的对象晋升
    Note over Eden,From: 清空 Eden 和 From
    To-&amp;gt;&amp;gt;From: To 变 From，From 变 To&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #6&lt;/strong&gt;：不要把 Survivor 区看作「两个对称缓存区」。它们在一次 Minor GC 后会&lt;strong&gt;交换身份&lt;/strong&gt;，始终有一个是空的，用于下一次复制目标。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;35-g1-收集器里程碑式的设计&#34;&gt;3.5 G1 收集器：里程碑式的设计&lt;/h3&gt;
&lt;p&gt;G1（Garbage First）把堆划分为多个大小相等的 Region，每个 Region 动态扮演 Eden、Survivor 或 Old 角色。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[G1 Heap Regions] --&amp;gt; B[Eden Region]
    A --&amp;gt; C[Survivor Region]
    A --&amp;gt; D[Old Region]
    A --&amp;gt; E[Humongous Region&amp;lt;br/&amp;gt;大对象]
    A --&amp;gt; F[Free Region]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;G1 的核心优势：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;可预测的停顿时间模型&lt;/strong&gt;：通过 &lt;code&gt;-XX:MaxGCPauseMillis&lt;/code&gt; 设定目标停顿。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;整体基于标记-整理，局部基于复制&lt;/strong&gt;：不会产生大面积内存碎片。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;回收优先级按垃圾最多的 Region 来&lt;/strong&gt;：Garbage First 名字来源。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #7&lt;/strong&gt;：G1 的 &lt;code&gt;-XX:MaxGCPauseMillis&lt;/code&gt; 不是越小越好。设得太低（如 50ms）会导致回收 Region 太少、GC 频率飙升，反而降低吞吐。通常建议 100-200ms。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;36-现代低延迟-gczgc-与-shenandoah&#34;&gt;3.6 现代低延迟 GC：ZGC 与 Shenandoah&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;特性&lt;/th&gt;
					&lt;th&gt;ZGC&lt;/th&gt;
					&lt;th&gt;Shenandoah&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;设计目标&lt;/td&gt;
					&lt;td&gt;亚毫秒级停顿，支持 TB 级堆&lt;/td&gt;
					&lt;td&gt;低停顿，独立于分代&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;并发能力&lt;/td&gt;
					&lt;td&gt;标记、转移、重定位几乎都并发&lt;/td&gt;
					&lt;td&gt;并发标记、并发压缩&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;着色指针&lt;/td&gt;
					&lt;td&gt;使用&lt;/td&gt;
					&lt;td&gt;不使用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;分代&lt;/td&gt;
					&lt;td&gt;JDK 21 引入分代 ZGC，JDK 23 起为默认&lt;/td&gt;
					&lt;td&gt;JDK 24 引入实验性分代 Shenandoah&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;适用版本&lt;/td&gt;
					&lt;td&gt;JDK 11+（生产推荐 JDK 17+）&lt;/td&gt;
					&lt;td&gt;OpenJDK 12+&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[传统 GC&amp;lt;br/&amp;gt;Serial/Parallel/CMS/G1] --&amp;gt;|停顿目标 ms~百 ms 级| B[G1]
    B --&amp;gt;|停顿目标 &amp;lt; 10ms| C[ZGC / Shenandoah]
    C --&amp;gt;|JDK 21+| D[分代 ZGC]
    D --&amp;gt;|JDK 23+| E[分代 ZGC 默认]
    C --&amp;gt;|JDK 24+| F[分代 Shenandoah 实验]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;高性能建议 #1&lt;/strong&gt;：如果应用对延迟敏感（如金融交易、在线游戏、实时推荐），JDK 17 下优先考虑 &lt;strong&gt;G1&lt;/strong&gt;；JDK 21+ 可直接启用 &lt;strong&gt;分代 ZGC&lt;/strong&gt;（&lt;code&gt;-XX:+UseZGC -XX:+ZGenerational&lt;/code&gt;），在吞吐和延迟之间取得更好平衡；升级到 &lt;strong&gt;JDK 23+&lt;/strong&gt; 后分代 ZGC 已是默认，无需额外参数。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;37-jdk-21222324-的-gc-演进大事记&#34;&gt;3.7 JDK 21/22/23/24 的 GC 演进大事记&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;JDK 版本&lt;/th&gt;
					&lt;th&gt;GC 相关变化&lt;/th&gt;
					&lt;th&gt;影响&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;JDK 21&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a href=&#34;https://openjdk.org/jeps/439&#34;&gt;JEP 439&lt;/a&gt; 正式发布&lt;strong&gt;分代 ZGC&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;默认仍是 G1，但可显式启用 &lt;code&gt;-XX:+ZGenerational&lt;/code&gt; 获得更低延迟&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;JDK 22&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a href=&#34;https://openjdk.org/jeps/423&#34;&gt;JEP 423&lt;/a&gt; G1 Region Pinning&lt;/td&gt;
					&lt;td&gt;G1 在 JNI 临界区内无需禁用 GC，降低延迟毛刺&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;JDK 23&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a href=&#34;https://openjdk.org/jeps/474&#34;&gt;JEP 474&lt;/a&gt; &lt;strong&gt;分代 ZGC 成为默认&lt;/strong&gt;；非分代 ZGC 废弃&lt;/td&gt;
					&lt;td&gt;新默认 GC 从 G1 切换到分代 ZGC，亚毫秒级停顿更易获得&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;JDK 23&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a href=&#34;https://bugs.openjdk.org/browse/JDK-8322630&#34;&gt;JDK-8322630&lt;/a&gt; ZGC 延迟优化&lt;/td&gt;
					&lt;td&gt;减少 GC 根节点扫描抖动&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;JDK 24&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a href=&#34;https://openjdk.org/jeps/490&#34;&gt;JEP 490&lt;/a&gt; 移除非分代 ZGC&lt;/td&gt;
					&lt;td&gt;简化 ZGC 维护，统一使用分代模式&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;JDK 24&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a href=&#34;https://openjdk.org/jeps/404&#34;&gt;JEP 404&lt;/a&gt; &lt;strong&gt;分代 Shenandoah（实验性）&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Shenandoah 也走向分代，未来低延迟 GC 竞争更激烈&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;JDK 24&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a href=&#34;https://openjdk.org/jeps/475&#34;&gt;JEP 475&lt;/a&gt; G1 Late Barrier Expansion&lt;/td&gt;
					&lt;td&gt;优化 G1 写屏障，提升编译和运行时性能&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;timeline
    title GC 默认与里程碑
    section JDK 8
        默认 : Parallel Scavenge + Parallel Old
    section JDK 9
        默认 : G1
    section JDK 11
        ZGC 实验性
    section JDK 15
        ZGC 生产可用
    section JDK 17
        G1 默认，ZGC/Shenandoah 成熟
    section JDK 21
        分代 ZGC 正式发布（仍非默认）
    section JDK 23
        分代 ZGC 成为默认 GC
    section JDK 24
        非分代 ZGC 移除；分代 Shenandoah 实验&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #7.5&lt;/strong&gt;：网上有说法称 &amp;ldquo;JDK 21 默认 GC 是 ZGC&amp;rdquo;，这是&lt;strong&gt;错误&lt;/strong&gt;的。JDK 21 默认仍是 &lt;strong&gt;G1&lt;/strong&gt;；分代 ZGC 只是正式发布，需要显式开启。真正的默认切换发生在 &lt;strong&gt;JDK 23&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四引用类型不只是强引用&#34;&gt;四、引用类型：不只是强引用&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;引用类型&lt;/th&gt;
					&lt;th&gt;回收时机&lt;/th&gt;
					&lt;th&gt;使用场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;强引用&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;永不回收，即使 OOM&lt;/td&gt;
					&lt;td&gt;普通对象&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;软引用 SoftReference&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;内存不足前回收&lt;/td&gt;
					&lt;td&gt;缓存，如图片缓存&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;弱引用 WeakReference&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;下一次 GC 时回收&lt;/td&gt;
					&lt;td&gt;防止内存泄漏，如 &lt;code&gt;WeakHashMap&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;虚引用 PhantomReference&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;随时可能被回收，必须配合 ReferenceQueue&lt;/td&gt;
					&lt;td&gt;跟踪对象被回收的事件，做资源后置清理&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[强引用] --&amp;gt;|最强| B[不会被回收]
    C[软引用] --&amp;gt;|内存紧张| D[回收]
    E[弱引用] --&amp;gt;|下次 GC| F[回收]
    G[虚引用] --&amp;gt;|无法获取对象| H[仅回收通知]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #8&lt;/strong&gt;：不要把软引用当「万能缓存」。在内存紧张时软引用会被批量回收，导致缓存命中率骤降。高并发缓存建议用 Caffeine 等带 TTL 和淘汰策略的专业缓存框架。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五类加载机制双亲委派与破坏&#34;&gt;五、类加载机制：双亲委派与破坏&lt;/h2&gt;
&lt;h3 id=&#34;51-类加载器层次&#34;&gt;5.1 类加载器层次&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[自定义类加载器] --&amp;gt;|委托| B[应用程序类加载器 AppClassLoader]
    B --&amp;gt;|委托| C[平台类加载器 PlatformClassLoader]
    C --&amp;gt;|委托| D[启动类加载器 BootstrapClassLoader]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：JDK 9 引入模块化系统后，原来的 &lt;strong&gt;Extension ClassLoader&lt;/strong&gt; 被改名为 &lt;strong&gt;Platform ClassLoader&lt;/strong&gt;，负责加载平台模块（如 &lt;code&gt;java.sql&lt;/code&gt;、&lt;code&gt;java.xml&lt;/code&gt; 等）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;52-双亲委派模型&#34;&gt;5.2 双亲委派模型&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;类加载器收到加载请求，先不自己加载。&lt;/li&gt;
&lt;li&gt;向上委托给父加载器。&lt;/li&gt;
&lt;li&gt;父加载器无法加载时，子加载器才尝试加载。&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #9&lt;/strong&gt;：Tomcat、SPI、OSGi 都&lt;strong&gt;破坏了双亲委派&lt;/strong&gt;。如果你的项目出现 &lt;code&gt;NoSuchMethodError&lt;/code&gt; / &lt;code&gt;ClassCastException: cannot cast to the same class&lt;/code&gt;，很可能是同一个类被不同类加载器加载了两次。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六jit-编译与执行优化&#34;&gt;六、JIT 编译与执行优化&lt;/h2&gt;
&lt;p&gt;Java 代码先被解释器执行，热点代码会被 JIT 编译成本地机器码。&lt;/p&gt;
&lt;h3 id=&#34;61-hotspot-的两层编译器&#34;&gt;6.1 HotSpot 的两层编译器&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;编译器&lt;/th&gt;
					&lt;th&gt;别称&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;C1&lt;/td&gt;
					&lt;td&gt;Client Compiler&lt;/td&gt;
					&lt;td&gt;编译快，优化简单，适合启动速度和 GUI&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;C2&lt;/td&gt;
					&lt;td&gt;Server Compiler&lt;/td&gt;
					&lt;td&gt;编译慢，激进优化，适合长期运行的服务端&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;JDK 7 引入&lt;strong&gt;分层编译&lt;/strong&gt;（Tiered Compilation），JDK 8 默认开启：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;0: 解释执行
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1~3: C1 编译，带简单/复杂优化
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;4: C2 编译，激进优化&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;62-常见-jit-优化&#34;&gt;6.2 常见 JIT 优化&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;优化&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;方法内联&lt;/td&gt;
					&lt;td&gt;把短方法体直接嵌入调用处，减少栈帧开销&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;逃逸分析&lt;/td&gt;
					&lt;td&gt;判断对象是否逃出方法/线程作用域&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;标量替换&lt;/td&gt;
					&lt;td&gt;把对象拆成基本类型分配在栈上&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;锁消除&lt;/td&gt;
					&lt;td&gt;确认对象只被单线程访问时去掉同步锁&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;锁粗化&lt;/td&gt;
					&lt;td&gt;把相邻的同步块合并，减少加解锁次数&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;高性能建议 #2&lt;/strong&gt;：不要过度纠结「每个对象都在堆上分配」。现代 JVM 的逃逸分析已经很强，写代码时优先保证&lt;strong&gt;对象作用域最小化&lt;/strong&gt;、&lt;strong&gt;避免无意义的全局引用&lt;/strong&gt;，让 JIT 有优化空间。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七现代-jvm-前沿特性jdk-21&#34;&gt;七、现代 JVM 前沿特性（JDK 21+）&lt;/h2&gt;
&lt;p&gt;除了 GC，JDK 21 及之后版本还在内存模型、执行模型和 Native 互操作上做了大量演进，这些也会间接影响 JVM 调优思路。&lt;/p&gt;
&lt;h3 id=&#34;71-虚拟线程virtual-threadsjep-444--jdk-21&#34;&gt;7.1 虚拟线程（Virtual Threads，JEP 444 / JDK 21）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;虚拟线程是 JVM 管理的轻量级线程，由 JVM 调度到少量平台线程（Carrier Thread）上运行。&lt;/li&gt;
&lt;li&gt;创建成本极低（KB 级栈），适合高并发 I/O 密集型应用。&lt;/li&gt;
&lt;li&gt;对 JVM 数据区的影响：虚拟线程的栈帧仍存在于 Java 堆中（作为 &lt;code&gt;Continuation&lt;/code&gt; 对象），而不是传统的线程栈。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[平台线程 Platform Thread] --&amp;gt;|1:N 映射| B[虚拟线程 Virtual Thread]
    B --&amp;gt;|挂载| C[Carrier Thread]
    C --&amp;gt;|运行在| D[OS 线程]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;避坑指南 #9.5&lt;/strong&gt;：虚拟线程虽好，但不要和 &lt;code&gt;synchronized&lt;/code&gt; 块、本地方法、文件 I/O 混用导致 &amp;ldquo;Pinning&amp;rdquo;，会让载体线程被卡住，降低并发收益。优先使用 &lt;code&gt;ReentrantLock&lt;/code&gt; 和异步 I/O。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;72-foreign-function--memory-apijep-454--jdk-22&#34;&gt;7.2 Foreign Function &amp;amp; Memory API（JEP 454 / JDK 22）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;正式替代 &lt;code&gt;sun.misc.Unsafe&lt;/code&gt; 进行堆外内存操作。&lt;/li&gt;
&lt;li&gt;通过 &lt;code&gt;Arena&lt;/code&gt; 管理堆外内存生命周期，更安全、更可移植。&lt;/li&gt;
&lt;li&gt;对直接内存调优的影响：未来 &lt;code&gt;DirectByteBuffer&lt;/code&gt; 的底层实现会逐步迁移到 FFM API。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;73-project-lilliput压缩对象头&#34;&gt;7.3 Project Lilliput：压缩对象头&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;目标是把 HotSpot 的对象头从 96/128 bit 压缩到 64 bit。&lt;/li&gt;
&lt;li&gt;可以显著降低内存占用，提升缓存命中率。&lt;/li&gt;
&lt;li&gt;JDK 24 起部分功能已集成（如 64-bit object headers）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;74-project-valhalla值类型value-classes--primitive-classes&#34;&gt;7.4 Project Valhalla：值类型（Value Classes / Primitive Classes）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;引入 &amp;ldquo;值对象&amp;rdquo;，避免对象头和引用开销。&lt;/li&gt;
&lt;li&gt;未来 &lt;code&gt;int[]&lt;/code&gt; 和 &lt;code&gt;Integer[]&lt;/code&gt; 之间的性能鸿沟会缩小。&lt;/li&gt;
&lt;li&gt;目前处于预览阶段，持续关注即可。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;75-project-leydenjava-静态镜像&#34;&gt;7.5 Project Leyden：Java 静态镜像&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;目标是通过 &amp;ldquo;静态图像&amp;rdquo; 加速 Java 启动时间。&lt;/li&gt;
&lt;li&gt;类似 GraalVM Native Image，但保持完整 Java 语义和 JVM 运行时能力。&lt;/li&gt;
&lt;li&gt;对 Serverless、CLI 工具、云原生场景意义重大。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;八避坑指南线上常见问题&#34;&gt;八、避坑指南：线上常见问题&lt;/h2&gt;
&lt;h3 id=&#34;81-慎用-systemgc&#34;&gt;8.1 慎用 &lt;code&gt;System.gc()&lt;/code&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;只是「建议」JVM 进行 Full GC，不保证执行。&lt;/li&gt;
&lt;li&gt;很多框架（如某些老版本 JDBC）会调用它，导致不可控停顿。&lt;/li&gt;
&lt;li&gt;线上建议关闭：&lt;code&gt;-XX:+DisableExplicitGC&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;82-finalize-已过时&#34;&gt;8.2 finalize() 已过时&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;JDK 9 起标记为 &lt;code&gt;@Deprecated&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;对象回收前不保证一定执行 &lt;code&gt;finalize()&lt;/code&gt;，且执行顺序不确定。&lt;/li&gt;
&lt;li&gt;资源清理用 &lt;code&gt;try-with-resources&lt;/code&gt; 或 &lt;code&gt;Cleaner&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;83-大对象与-humongous&#34;&gt;8.3 大对象与 Humongous&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;G1 中超过 Region 大小一半的对象叫 Humongous Object，直接进老年代，增加 GC 负担。&lt;/li&gt;
&lt;li&gt;避免一次性创建超大数组或字符串。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;84-动态代理与-cglib-的-metaspace-泄漏&#34;&gt;8.4 动态代理与 CGLIB 的 Metaspace 泄漏&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Spring AOP、MyBatis、Dubbo 大量生成代理类。&lt;/li&gt;
&lt;li&gt;如果 ClassLoader 没释放，代理类元数据会持续占用 Metaspace。&lt;/li&gt;
&lt;li&gt;常见于热部署、OSGi、动态脚本场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;85-大堆--full-gc-的雪崩&#34;&gt;8.5 大堆 + Full GC 的雪崩&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;堆内存越大，G1 的 Mixed GC、CMS 的 Full GC 停顿越长。&lt;/li&gt;
&lt;li&gt;超过 32GB 时，指针压缩会失效，对象头变大，反而浪费内存。&lt;/li&gt;
&lt;li&gt;建议堆大小控制在 16GB-32GB 之间，再大的堆考虑横向拆分服务或换 ZGC。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九高性能调优建议&#34;&gt;九、高性能调优建议&lt;/h2&gt;
&lt;h3 id=&#34;91-选择-gc-与-jdk-版本&#34;&gt;9.1 选择 GC 与 JDK 版本&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;场景&lt;/th&gt;
					&lt;th&gt;推荐配置&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;通用 Web 服务，JDK 17-22&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-XX:+UseG1GC -XX:MaxGCPauseMillis=200&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;通用 Web 服务，&lt;strong&gt;JDK 23+&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;默认已是分代 ZGC，一般无需改动&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;延迟敏感，JDK 21-22&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-XX:+UseZGC -XX:+ZGenerational&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;延迟敏感，JDK 23+&lt;/td&gt;
					&lt;td&gt;默认分代 ZGC，无需显式开启&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;批处理/大数据，吞吐优先&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;-XX:+UseParallelGC&lt;/code&gt; 或 G1&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;容器环境&lt;/td&gt;
					&lt;td&gt;显式设置 &lt;code&gt;-Xmx&lt;/code&gt;、&lt;code&gt;-Xms&lt;/code&gt;、&lt;code&gt;-XX:MaxMetaspaceSize&lt;/code&gt;，并开启 &lt;code&gt;-XX:+UseContainerSupport&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;92-参数模板&#34;&gt;9.2 参数模板&lt;/h3&gt;
&lt;h4 id=&#34;jdk-17-22-通用-web-服务g1&#34;&gt;JDK 17-22 通用 Web 服务（G1）&lt;/h4&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms4g -Xmx4g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseG1GC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -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; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar app.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h4 id=&#34;jdk-23-通用-web-服务默认分代-zgc&#34;&gt;JDK 23+ 通用 Web 服务（默认分代 ZGC）&lt;/h4&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms4g -Xmx4g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xlog:gc*:file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/gc.log:time,uptime,level,tags:filecount&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;10,filesize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;100m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar app.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;说明&lt;/strong&gt;：JDK 23 起默认就是分代 ZGC，不需要 &lt;code&gt;-XX:+UseZGC&lt;/code&gt;。如果仍想显式启用，可保留；如果想用回 G1，使用 &lt;code&gt;-XX:+UseG1GC&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;93-监控与诊断三板斧&#34;&gt;9.3 监控与诊断三板斧&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;用途&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jstat -gcutil &amp;lt;pid&amp;gt; 1000&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;实时查看 GC 频率与内存占比&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jmap -dump:format=b,file=... &amp;lt;pid&amp;gt;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;生成堆快照，MAT 分析内存泄漏&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jstack &amp;lt;pid&amp;gt;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;打印线程栈，排查死锁与 CPU 热点&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;GC 日志 / &lt;code&gt;-Xlog:gc*&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;分析 GC 原因与停顿时间&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;async-profiler&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;低开销 CPU/内存/锁分析&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;高性能建议 #3&lt;/strong&gt;：调优前一定先&lt;strong&gt;定目标&lt;/strong&gt;——是降低停顿？提高吞吐？还是减少内存？没有目标的调优就是瞎调。先用 GC 日志和监控找到瓶颈，再改参数，而不是反向操作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十jvm-问题排查实战发现--定位--修复&#34;&gt;十、JVM 问题排查实战：发现 → 定位 → 修复&lt;/h2&gt;
&lt;p&gt;线上 JVM 问题通常表现为：服务卡顿、响应 P99 飙高、CPU 打满、内存持续增长、频繁 OOM。解决它们的核心思路是：&lt;strong&gt;先量化，再猜测&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;101-问题发现的四层入口&#34;&gt;10.1 问题发现的四层入口&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[业务层] --&amp;gt;|接口超时/P99 飙升| B[应用层]
    B --&amp;gt;|Full GC 频繁/GC 时间长| C[JVM 层]
    C --&amp;gt;|堆/栈/Metaspace 异常| D[系统层]
    D --&amp;gt;|容器 OOMKilled/CPU 限流| E[基础设施层]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;入口&lt;/th&gt;
					&lt;th&gt;典型现象&lt;/th&gt;
					&lt;th&gt;常见根因&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;业务监控&lt;/td&gt;
					&lt;td&gt;接口 RT 上涨、错误率增加&lt;/td&gt;
					&lt;td&gt;GC 停顿、线程阻塞、锁竞争&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;APM / Trace&lt;/td&gt;
					&lt;td&gt;某段链路偶发耗时几百 ms&lt;/td&gt;
					&lt;td&gt;Full GC、Metaspace 扩容、类加载&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;容器监控&lt;/td&gt;
					&lt;td&gt;Pod 内存触顶被 OOMKilled&lt;/td&gt;
					&lt;td&gt;堆外内存泄漏、堆太大、Metaspace 无上限&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;GC 日志&lt;/td&gt;
					&lt;td&gt;GC 频率异常、停顿时间超标&lt;/td&gt;
					&lt;td&gt;收集器选择不当、堆大小不合理、大对象过多&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;JVM 告警&lt;/td&gt;
					&lt;td&gt;Heap 使用率 &amp;gt; 85%、FGC 次数突增&lt;/td&gt;
					&lt;td&gt;内存泄漏、流量突增、缓存失控&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;102-排查工具箱&#34;&gt;10.2 排查工具箱&lt;/h3&gt;
&lt;h4 id=&#34;1021-命令行工具适合快速止血&#34;&gt;10.2.1 命令行工具（适合快速止血）&lt;/h4&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;命令&lt;/th&gt;
					&lt;th&gt;场景&lt;/th&gt;
					&lt;th&gt;输出重点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jps -lvm&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;找到 Java 进程 PID&lt;/td&gt;
					&lt;td&gt;主类名、启动参数&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jstat -gcutil &amp;lt;pid&amp;gt; 1000&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;实时监控 GC 与内存&lt;/td&gt;
					&lt;td&gt;S0/S1/E/O/M 各区使用率、YGC/FGC 次数&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jmap -heap &amp;lt;pid&amp;gt;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;查看堆配置与概览&lt;/td&gt;
					&lt;td&gt;新生代/老年代大小、收集器&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jmap -histo &amp;lt;pid&amp;gt;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;查看对象直方图&lt;/td&gt;
					&lt;td&gt;哪个类实例数/占用最多&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jmap -dump:format=b,file=... &amp;lt;pid&amp;gt;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;生成堆 dump&lt;/td&gt;
					&lt;td&gt;配合 MAT / JProfiler 分析&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jstack &amp;lt;pid&amp;gt;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;打印线程栈&lt;/td&gt;
					&lt;td&gt;死锁、CPU 热点线程、Blocked 线程&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jcmd &amp;lt;pid&amp;gt; VM.native_memory summary&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;查看 Native Memory Tracking&lt;/td&gt;
					&lt;td&gt;堆外内存、Metaspace、Symbol 区占用&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;1022-可视化--专业工具&#34;&gt;10.2.2 可视化 / 专业工具&lt;/h4&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;工具&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
					&lt;th&gt;特点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;MAT (Eclipse Memory Analyzer)&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;分析堆 dump&lt;/td&gt;
					&lt;td&gt;大对象、内存泄漏、支配树、Leak Suspects&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;JProfiler / YourKit&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;全链路 JVM 分析&lt;/td&gt;
					&lt;td&gt;CPU、内存、线程、GC 一体化&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;async-profiler&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;生产环境火焰图&lt;/td&gt;
					&lt;td&gt;低开销，适合线上持续采样&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;GCViewer / GCEasy&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;解析 GC 日志&lt;/td&gt;
					&lt;td&gt;可视化 GC 事件、停顿分布&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Prometheus + Grafana&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;长期监控与告警&lt;/td&gt;
					&lt;td&gt;自定义 JVM 指标大盘&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Arthas&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;线上实时诊断&lt;/td&gt;
					&lt;td&gt;无需重启，支持 trace、watch、thread、heapdump&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;103-典型问题排查流程&#34;&gt;10.3 典型问题排查流程&lt;/h3&gt;
&lt;h4 id=&#34;场景-1cpu-飙升&#34;&gt;场景 1：CPU 飙升&lt;/h4&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;# 1. 找到 CPU 占用最高的线程&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ps -mp &amp;lt;pid&amp;gt; -o THREAD,tid,time | sort -rn
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&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;# 2. 把 tid 转成十六进制&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;printf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%x\n&amp;#34;&lt;/span&gt; &amp;lt;tid&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&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;# 3. 用 jstack 查看对应线程栈&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jstack &amp;lt;pid&amp;gt; | grep -A &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt; &amp;lt;hex_tid&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;常见根因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;死循环或复杂正则&lt;/li&gt;
&lt;li&gt;Young GC 过于频繁&lt;/li&gt;
&lt;li&gt;JIT 编译器 C2 线程忙碌（启动期正常）&lt;/li&gt;
&lt;li&gt;大量 &lt;code&gt;ThreadLocal&lt;/code&gt; 未清理&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;场景-2内存持续增长--oom&#34;&gt;场景 2：内存持续增长 / OOM&lt;/h4&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;# 1. 确认哪个区域增长&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jstat -gcutil &amp;lt;pid&amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&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;# 2. 开启 Native Memory Tracking&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jcmd &amp;lt;pid&amp;gt; VM.native_memory baseline
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jcmd &amp;lt;pid&amp;gt; VM.native_memory summary.diff
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&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;# 3. 触发堆 dump（若还能响应）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jmap -dump:live,format&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;b,file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/tmp/heap.hprof &amp;lt;pid&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;常见根因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;堆：缓存无淘汰、大对象、集合只增不减&lt;/li&gt;
&lt;li&gt;Metaspace：动态代理/CGLIB 类加载器泄漏&lt;/li&gt;
&lt;li&gt;堆外：Netty &lt;code&gt;ByteBuf&lt;/code&gt; 未释放、NIO DirectBuffer 堆积&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;场景-3接口偶发卡顿--p99-高&#34;&gt;场景 3：接口偶发卡顿 / P99 高&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;打开 GC 日志，看是否有 &lt;strong&gt;长停顿&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;jstack&lt;/code&gt; 抓取卡顿时刻线程栈，看是否有大量 &lt;code&gt;BLOCKED&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;async-profiler&lt;/code&gt; 采集 CPU 火焰图，定位热点方法。&lt;/li&gt;
&lt;li&gt;检查是否有 &lt;code&gt;System.gc()&lt;/code&gt;、Metaspace 扩容、类加载抖动。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;104-jvm-监控告警建议&#34;&gt;10.4 JVM 监控告警建议&lt;/h3&gt;
&lt;p&gt;建议把以下指标接入 Prometheus + Grafana，并设置合理阈值：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;指标&lt;/th&gt;
					&lt;th&gt;告警阈值建议&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jvm_memory_used_bytes / jvm_memory_max_bytes&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt; 85%&lt;/td&gt;
					&lt;td&gt;堆/非堆内存使用率&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jvm_gc_pause_seconds_sum&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;P99 &amp;gt; 200ms&lt;/td&gt;
					&lt;td&gt;GC 停顿时间&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jvm_gc_memory_allocated_bytes_total&lt;/code&gt; 增长率&lt;/td&gt;
					&lt;td&gt;突增 2 倍以上&lt;/td&gt;
					&lt;td&gt;对象分配速率异常&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jvm_classes_loaded_total&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;持续增长&lt;/td&gt;
					&lt;td&gt;类泄漏嫌疑&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;process_cpu_usage&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt; 80% 持续 5min&lt;/td&gt;
					&lt;td&gt;CPU 压力&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;jvm_threads_live&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;突增或接近上限&lt;/td&gt;
					&lt;td&gt;线程泄漏&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;容器维度 &lt;code&gt;container_memory_working_set_bytes&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&amp;gt; 90% limit&lt;/td&gt;
					&lt;td&gt;容器 OOMKilled 预警&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[应用埋点] --&amp;gt;|Micrometer| B[Prometheus]
    C[GC 日志] --&amp;gt;|Loki / Filebeat| D[日志平台]
    B --&amp;gt; E[Grafana 大盘]
    D --&amp;gt; E
    E --&amp;gt;|阈值触发| F[AlertManager]
    F --&amp;gt;|通知| G[钉钉/企业微信/Slack]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;十一不同场景的-jvm-配置策略&#34;&gt;十一、不同场景的 JVM 配置策略&lt;/h2&gt;
&lt;h3 id=&#34;111-配置前的通用原则&#34;&gt;11.1 配置前的通用原则&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;先压测，再调优&lt;/strong&gt;：没有真实流量数据，调参都是拍脑袋。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Xms = Xmx&lt;/strong&gt;：避免运行时堆扩容带来的 GC 抖动。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metaspace 必须设上限&lt;/strong&gt;：容器环境下尤其重要。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GC 日志一定要开&lt;/strong&gt;：&lt;code&gt;-Xlog:gc*&lt;/code&gt;（JDK 9+）成本很低，信息无价。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;容器环境开启 Container Support&lt;/strong&gt;：&lt;code&gt;-XX:+UseContainerSupport&lt;/code&gt;（JDK 8u191+/10+ 默认开启）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不要堆内存无限大&lt;/strong&gt;：超过 32GB 指针压缩失效，性价比骤降。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;112-场景一高并发-web--api-服务&#34;&gt;11.2 场景一：高并发 Web / API 服务&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;特征&lt;/strong&gt;：QPS 高、对象生命周期短、响应延迟敏感。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：降低 GC 停顿、控制 P99。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;推荐配置（JDK 17-22，G1）&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms4g -Xmx4g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseG1GC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxGCPauseMillis&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:InitiatingHeapOccupancyPercent&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;35&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xlog:gc*:file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/gc.log:time,uptime,level,tags:filecount&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;10,filesize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;100m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar app.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;推荐配置（JDK 23+，默认分代 ZGC）&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms4g -Xmx4g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xlog:gc*:file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/gc.log:time,uptime,level,tags:filecount&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;10,filesize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;100m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar app.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;调优要点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新生代尽量大，让短生命周期对象在 Young GC 回收。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-XX:MaxGCPauseMillis&lt;/code&gt; 根据业务容忍度设置，100-200ms 常见。&lt;/li&gt;
&lt;li&gt;监控 &lt;code&gt;jvm_gc_pause_seconds_sum&lt;/code&gt;，若频繁触发 Mixed GC，考虑增大 &lt;code&gt;-XX:InitiatingHeapOccupancyPercent&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;113-场景二高流量--削峰填谷消息队列消费者&#34;&gt;11.3 场景二：高流量 / 削峰填谷（消息队列消费者）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;特征&lt;/strong&gt;：突发流量、消息处理批量化、吞吐优先、允许一定延迟。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：提高吞吐，避免 OOM 和 Full GC。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;推荐配置&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms8g -Xmx8g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseG1GC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxGCPauseMillis&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;300&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:G1HeapRegionSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;16m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:InitiatingHeapOccupancyPercent&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;40&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xlog:gc*:file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/gc.log:time,uptime,level,tags:filecount&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;10,filesize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;100m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar consumer.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;调优要点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;堆可以比 Web 服务稍大，因为要缓冲突发消息。&lt;/li&gt;
&lt;li&gt;批量消费时注意控制单次拉取消息数，避免一次创建过多对象。&lt;/li&gt;
&lt;li&gt;如果业务允许更高延迟，可考虑 &lt;code&gt;-XX:+UseParallelGC&lt;/code&gt; 追求极致吞吐。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;114-场景三低延迟金融--交易--实时推荐&#34;&gt;11.4 场景三：低延迟金融 / 交易 / 实时推荐&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;特征&lt;/strong&gt;：P99 要求 &amp;lt; 10ms，任何 GC 停顿都可能导致业务损失。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：亚毫秒级 GC 停顿。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;推荐配置（JDK 21+）&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms16g -Xmx16g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseZGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+ZGenerational &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xlog:gc*:file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/gc.log:time,uptime,level,tags:filecount&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;10,filesize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;100m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar trading.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;JDK 23+ 可简化为&lt;/strong&gt;（默认就是分代 ZGC）：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms16g -Xmx16g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xlog:gc*:file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/gc.log:time,uptime,level,tags:filecount&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;10,filesize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;100m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar trading.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;调优要点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;堆 &amp;gt; 16GB 时 ZGC 优势更明显。&lt;/li&gt;
&lt;li&gt;避免大对象（Humongous），ZGC 对大对象分配路径不如小对象高效。&lt;/li&gt;
&lt;li&gt;监控 &lt;code&gt;jvm_gc_pause_seconds_max&lt;/code&gt;，正常应在 1ms 以内。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;115-场景四大数据--批处理--etl&#34;&gt;11.5 场景四：大数据 / 批处理 / ETL&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;特征&lt;/strong&gt;：长时间运行、对象存活久、吞吐优先、延迟不敏感。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：最大化吞吐，减少总 GC 时间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;推荐配置&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms16g -Xmx16g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;1g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseParallelGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:ParallelGCThreads&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseLargePages &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xlog:gc*:file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/gc.log:time,uptime,level,tags:filecount&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;10,filesize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;100m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar etl.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;调优要点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parallel GC 在纯吞吐场景下通常优于 G1。&lt;/li&gt;
&lt;li&gt;大堆 + 大页（LargePages）减少 TLB miss。&lt;/li&gt;
&lt;li&gt;如果批处理任务会频繁 Full GC，考虑分阶段释放引用或使用堆外缓存。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;116-场景五容器--k8s-微服务&#34;&gt;11.6 场景五：容器 / K8s 微服务&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;特征&lt;/strong&gt;：资源受限、弹性伸缩、多实例共享节点。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：稳定、不 OOMKilled、启动快。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;推荐配置&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseContainerSupport &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:InitialRAMPercentage&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;70.0 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxRAMPercentage&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;70.0 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;128m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseG1GC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -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; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xlog:gc*:file&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/gc.log:time,uptime,level,tags:filecount&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;5,filesize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;50m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar service.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;调优要点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 &lt;code&gt;-XX:MaxRAMPercentage&lt;/code&gt; 替代固定 &lt;code&gt;-Xmx&lt;/code&gt;，适配不同 Limit。&lt;/li&gt;
&lt;li&gt;容器 memory limit 要预留 10%-20% 给堆外内存、Metaspace、线程栈、JVM 自身。&lt;/li&gt;
&lt;li&gt;不要把 &lt;code&gt;-Xmx&lt;/code&gt; 设成容器 limit 的 100%，否则容易被 OOMKilled。&lt;/li&gt;
&lt;li&gt;JDK 23+ 在容器里可直接用默认分代 ZGC。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;117-场景六spring-boot--微服务网关&#34;&gt;11.7 场景六：Spring Boot / 微服务网关&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;特征&lt;/strong&gt;：启动时大量类加载、反射多、动态代理多。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目标&lt;/strong&gt;：启动快 + 运行稳。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;推荐配置&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&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;java &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Xms2g -Xmx2g &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;256m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxMetaspaceSize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;512m &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+UseG1GC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:MaxGCPauseMillis&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;150&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+AlwaysPreTouch &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+DisableExplicitGC &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:+HeapDumpOnOutOfMemoryError &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -XX:HeapDumpPath&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/log/app/heapdump.hprof &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -Dspring.backgroundpreinitializer.ignore&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;true &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -jar gateway.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;调优要点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Spring Boot 启动时 Metaspace 会快速上涨，初始值不要设太小。&lt;/li&gt;
&lt;li&gt;如果启动慢，可用 &lt;code&gt;-XX:+TieredCompilation&lt;/code&gt; 配合 &lt;code&gt;-XX:TieredStopAtLevel=1&lt;/code&gt; 加速启动（牺牲峰值性能）。&lt;/li&gt;
&lt;li&gt;网关避免在请求路径创建大对象，优先复用对象和缓冲区。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十二一句话总结&#34;&gt;十二、一句话总结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;内存&lt;/strong&gt;：堆内分代、堆外 Direct、Metaspace 存类元数据；虚拟线程栈帧在堆中。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GC&lt;/strong&gt;：Serial → Parallel → CMS → G1 → &lt;strong&gt;分代 ZGC&lt;/strong&gt;；JDK 21 分代 ZGC 正式发布，&lt;strong&gt;JDK 23 起成为默认 GC&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;引用&lt;/strong&gt;：强 &amp;gt; 软 &amp;gt; 弱 &amp;gt; 虚，缓存别滥用软引用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能&lt;/strong&gt;：JDK 17-22 优先 G1；JDK 23+ 默认分代 ZGC；延迟极致用 ZGC，吞吐优先用 Parallel。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;排查&lt;/strong&gt;：监控先行 → 日志定位 → 工具分析 → 压测验证 → 持续观察。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;场景&lt;/strong&gt;：Web 服务控延迟、消息队列保吞吐、金融交易用 ZGC、批处理用 Parallel、容器环境留余量。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;JVM 调优没有银弹，但有方法论：&lt;strong&gt;理解数据区 → 选对收集器 → 设定合理目标 → 用日志验证 → 持续监控&lt;/strong&gt;。把这套流程跑熟，面试八股和线上救火就都不慌了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;参考&#34;&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;《深入理解 Java 虚拟机》（第三版）周志明&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.oracle.com/en/java/javase/21/gctuning/&#34;&gt;OpenJDK HotSpot Virtual Machine Garbage Collection Tuning Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/333&#34;&gt;JEP 333: ZGC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/439&#34;&gt;JEP 439: Generational ZGC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/474&#34;&gt;JEP 474: ZGC Generational Mode by Default&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/490&#34;&gt;JEP 490: Remove the Non-Generational ZGC Mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/404&#34;&gt;JEP 404: Generational Shenandoah (Experimental)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/444&#34;&gt;JEP 444: Virtual Threads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/jeps/454&#34;&gt;JEP 454: Foreign Function &amp;amp; Memory API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://openjdk.org/projects/lilliput/&#34;&gt;Project Lilliput&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
