发布时间:2026/7/30 23:56:09
【JVM原理详解】25-Serial与ParNew收集器 25-Serial 与 ParNew 收集器前面几篇讲的是算法从本篇开始进入实现——具体到 HotSpot 提供的几种垃圾收集器。最古老、也是最简单的就是Serial和Serial Old收集器它们是理解后续所有收集器的基础。ParNew则是 Serial 的多线程版本专为配合 CMS 而生。本篇将剖析它们的设计、参数、组合关系与适用场景。Serial 收集器Serial 是 HotSpot 最古老的收集器单线程回收回收时必须 STWStop The World期间所有应用线程挂起。它的新生代采用复制算法老年代对应的是 Serial OldMark-Compact。应用线程: ████░░░░░░░░████████... ↑ Serial STW设计哲学单线程听起来落后但它的优势恰恰是简单没有线程同步、协调开销单次 GC 的 CPU 利用率高。适合单核或小内存环境。在 Client 模式或嵌入式设备上Serial 是默认选择。即使在现代 JDK 中它依然是新生代默认收集器候选取决于平台和 JDK 版本。Serial OldSerial Old 是 Serial 的老年代版本同样单线程采用 Mark-Compact 算法。它主要有两个用途在 Client 模式下与 Serial 配套。作为 CMS 的后备——当 CMS 出现 Concurrent Mode Failure 时退化为 Serial Old 执行 Full GC。第二种场景在 JDK 8 CMS 的生产环境中是出了名的长停顿来源也是 CMS 被废弃的重要原因。关键参数# 显式指定使用 Serial Serial Oldjava-XX:UseSerialGC-cpMyApp com.example.Main-XX:UseSerialGC等同于同时启用 Serial新生代与 Serial Old老年代。JDK 8 在 Client 模式下默认就是这套组合。代码示例与日志分析/** * 演示 Serial GC 行为 * 适用 JDK 8/11/17 * * 运行 * java -Xms20m -Xmx20m -Xmn10m * -XX:SurvivorRatio8 -XX:UseSerialGC * -Xlog:gc*info -cp MyApp SerialGcDemo */publicclassSerialGcDemo{privatestaticfinalint_1MB1024*1024;publicstaticvoidmain(String[]args)throwsException{for(inti0;i8;i){byte[]blocknewbyte[2*_1MB];System.out.println(allocated i - block.length);Thread.sleep(300);}}}JDK 11 日志-Xlog:gc*info[0.123s][info][gc,start] GC(0) Pause Young (Allocation Failure) [0.123s][info][gc,task] GC(0) Using 1 workers [0.124s][info][gc,heap] GC(0) DefNew total 9216K, used 8000K [0.124s][info][gc,heap] GC(0) Eden space 8192K, 100% used [0.124s][info][gc,heap] GC(0) From space 1024K, 0% used [0.124s][info][gc,heap] GC(0) To space 1024K, 0% used [0.124s][info][gc,heap] GC(0) Tenured generation total 10240K, used 0K [0.124s][info][gc] GC(0) Pause Young (Allocation Failure) 7M-1M(20M) 1.234ms关注几个关键字段DefNewDefault New GenerationSerial 新生代的内部名。Using 1 workers单线程回收。7M-1M(20M)回收前 7M回收后 1M堆总大小 20M。1.234ms本次 GC 停顿。老年代 Full GC 日志[5.678s][info][gc,start] GC(5) Pause Full (Allocation Failure) [5.678s][info][gc,heap] GC(5) Tenured generation total 10240K, used 8000K [5.679s][info][gc] GC(5) Pause Full (Allocation Failure) 18M-12M(20M) 5.678msTenured是 Serial Old 老年代名。可以看到 Full GC 的停顿比 Minor GC 长得多——这是 Mark-Compact 算法的固有代价。ParNew 收集器ParNew 是 Serial 的多线程版本新生代复制算法、STW但回收时用多个 GC 线程并行。它是唯一能与 CMS 配合的新生代收集器。应用线程: ████░░░░░░░░████████... ↑ ParNew STW多 GC 线程并行与 Serial 的关系ParNew 在单核环境下不会比 Serial 更快——多线程协调反而有额外开销。但在多核环境下多线程并行能显著缩短 STW 时间单线程: ████████████ (12ms) 4线程: ███ (3ms)这也是吞吐量 vs 延迟的早期权衡ParNew 通过并行降低单次停顿但总 CPU 开销与 Serial 相当甚至略高。关键参数# JDK 8显式启用 ParNew CMSjava-XX:UseParNewGC-XX:UseConcMarkSweepGC-cpMyApp com.example.Main# 控制并行 GC 线程数java-XX:UseParNewGC-XX:ParallelGCThreads4-cpMyApp com.example.MainParallelGCThreads默认值与 CPU 核数相关核数 ≤ 8 时等于核数否则为3 5N/8N 为核数。在容器化部署中建议显式设置避免误用宿主机核数。ParNew 的局限ParNew 只能回收新生代必须与一个老年代收集器搭配。JDK 8 可用组合ParNew CMS推荐低延迟ParNew Serial Old退化不推荐JDK 9 起由于 CMS 被标记 deprecatedParNew 也被限制-XX:UseParNewGC单独使用会报警告最终在 JDK 14 随 CMS 一起被移除。新代码应直接用 G1。收集器组合关系HotSpot 不同代际收集器的组合关系是有限制的。下表是 JDK 8 的合法组合新生代老年代说明SerialSerial OldClient 模式、嵌入式ParNewCMS低延迟首选ParNewSerial Old不推荐仅兼容性Parallel ScavengeParallel Old吞吐量优先G1自身分代JDK 9 默认注意ParNew Parallel Old不是合法组合。原因是 ParNew 与 CMS 共享代码框架Parallel Scavenge 走的是另一套实现。这种组合限制常常是面试题的考点也是 JDK 9 后统一向 G1 收敛的内在动因。选型决策树堆 100MB → Serial Client/嵌入式 → Serial 吞吐量优先批处理 → Parallel Scavenge Parallel Old 低延迟JDK 8 → ParNew CMS 低延迟JDK 11 → G1或 ZGC 超低延迟JDK 15 → ZGC / Shenandoah代码示例对比 Serial 与 ParNew下面这段代码在两种收集器下运行对比 GC 日志差异/** * Serial vs ParNew 对比 * 适用 JDK 8 */publicclassCollectorCompare{privatestaticfinalint_1MB1024*1024;publicstaticvoidmain(String[]args)throwsException{// 持续分配制造 GC 压力for(inti0;i50;i){byte[]blocknewbyte[512*1024];Thread.sleep(50);}}}运行命令# Serialjava-Xmx200m-Xmn100m-XX:UseSerialGC\-Xlog:gc*info-cpMyApp CollectorCompare# ParNew CMSjava-Xmx200m-Xmn100m-XX:UseParNewGC-XX:UseConcMarkSweepGC\-Xlog:gc*info-cpMyApp CollectorCompare对比日志关键字段字段SerialParNew新生代名DefNewParNewGC 线程数Using 1 workersUsing 8 workers单次停顿较长较短多核时典型输出8 核机器200M 堆# Serial [0.045s][info][gc] GC(0) Pause Young (Allocation Failure) 60M-10M(200M) 4.321ms # ParNew [0.038s][info][gc] GC(0) Pause Young (Allocation Failure) 60M-10M(200M) 1.102ms多核环境下 ParNew 的停顿显著低于 Serial。但在单核或极小堆上Serial 因无线程协调开销可能反而更快。适用场景Serial / Serial Old嵌入式设备内存小数十 MB、CPU 弱单线程更高效。Client 模式桌面应用堆不大、对停顿不敏感。微服务预热阶段某些框架在启动期用 Serial 减少开销。教学/调试日志简单便于理解 GC 原理。ParNewJDK 8 CMS 的低延迟应用Web 服务、交易系统等对 STW 敏感的场景。多核中小堆堆在 4GB 以内时ParNew CMS 仍是合理选择。JDK 9 不再推荐应迁移到 G1。迁移建议如果你的系统还在用 ParNew CMSJDK 11切换到 G1通常能获得相近或更好的延迟表现。JDK 17评估 ZGC 或 Shenandoah追求个位数毫秒级停顿。迁移前用 GC 日志工具如 GCEasy分析现有 GC 模式作为基线对比。实践要点1.-XX:UseParallelGC不等于 ParNewJDK 8 中-XX:UseParallelGC启用的是Parallel Scavenge Parallel Old不是 ParNew。两者代码不同、组合不互通。命名容易混淆需特别注意。2. 容器中的 GC 线程数Docker/K8s 环境下JVM 可能误识别宿主机核数导致 GC 线程过多。建议显式设置java-XX:ParallelGCThreads4-XX:ConcGCThreads2-cpMyApp com.example.MainJDK 10 的容器感知-XX:UseContainerSupport默认开启已能自动识别 cgroup 限制但显式设置更稳妥。3. 日志格式统一JDK 9 引入统一日志格式-Xlog:JDK 8 用-XX:PrintGCDetails。迁移时记得转换参数# JDK 8-XX:PrintGCDetails-XX:PrintGCDateStamps-Xloggc:gc.log# JDK 11-Xlog:gc*info:filegc.log:time,uptime,level,tags4. 小堆场景下 Serial 可能更优堆小于 100MB 时多线程协调的开销可能超过并行收益。这时-XX:UseSerialGC反而更好。某些 IoT 场景就是如此。5. GC 日志分析工具GCEasygceasy.io在线分析给出停顿、吞吐量、内存分布等指标。GCViewer本地工具适合离线分析。JDK Mission ControlJMCJDK 11 自带可关联 GC 事件与应用行为。小结Serial / Serial Old单线程、STW、实现简单适合嵌入式和 Client 场景新生代用复制算法老年代用 Mark-Compact。ParNewSerial 的多线程版本新生代复制算法配合 CMS 使用JDK 9 起逐步退出历史舞台。收集器组合有严格限制ParNew 只能与 CMS / Serial Old 搭配不能与 Parallel Old 组合。容器化部署应显式设置ParallelGCThreads避免误用宿主机核数。现代应用建议直接使用 G1JDK 9 默认或 ZGC/ShenandoahJDK 15Serial/ParNew 仅在特定小内存或历史系统中保留。本模块至此完成了从判定对象存活到基础回收算法再到早期收集器的脉络。下一篇我们将进入更现代的收集器——Parallel Scavenge 与 CMS——继续探讨吞吐量与延迟的权衡。更多内容JVM调优实战

相关新闻

2026/7/30 23:56:09

【JVM原理详解】24-垃圾回收算法-标记清除复制整理分代

24-垃圾回收算法:标记-清除、复制、整理与分代 知道了"哪些对象活着、哪些该死",下一步就是"如何高效回收死对象"。GC 算法经过几十年的演化,沉淀出四种基础范式:Mark-Sweep(标记-清除&#xff0…

2026/7/30 23:51:08

basic-ftp源码探秘:Typescript实现的FTP协议解析原理

basic-ftp源码探秘:Typescript实现的FTP协议解析原理 【免费下载链接】basic-ftp FTP client for Node.js, supports FTPS over TLS, passive mode over IPv6, async/await, and Typescript. 项目地址: https://gitcode.com/gh_mirrors/ba/basic-ftp basic-f…

2026/7/31 0:46:38

MCP的STDIO、Streamable HTTP与Stateless HTTP怎么选?三种传输架构指南

文章摘要 MCP在Java和Spring AI项目中常见三种部署方式:STDIO适合本地进程工具,Streamable HTTP适合需要会话和双向能力的远程服务,Stateless HTTP则适合请求—响应型工具和云原生水平扩容。三种方式在网络边界、状态管理、Sampling、Elicita…

2026/7/31 0:46:38

智算中心供电方案:从架构演进到关键产品选型的深度解析

2025年以来,AI大模型参数规模以每18个月增长10倍的速度持续膨胀,单机柜功率从传统的6-8kW快速跃升至40kW乃至100kW以上,一座中等规模的智算中心用电负荷动辄达到30MW至100MW。电力供给已从后台保障问题,上升为决定智算中心能否稳定…

2026/7/31 0:46:38

差分高速线路设计高频踩坑点避坑指南

一、差分线路工作底层逻辑,厘清差分设计最容易混淆的基础概念差分传输依靠两条极性相反的信号走线同步传输数据,接收端识别两条线路的电压差值解析信号内容。差分架构两大核心优势:其一,外界空间辐射干扰会同步耦合至两根差分线上…

2026/7/29 22:32:30

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

2026/7/31 0:01:11

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:01:11

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:01:11

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:38:56

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…