实战篇-java8中的垃圾回收器

news/2025/2/26 6:01:51

1. 背景

java8中默认使用parallel scavenge + parallel old的组合。当然我们也可使用parnew + cms或g1的方案。
在实际应用过程中,如果ygc和fgc都比较少,如ygc一天几次或者一小时几次,其实我们都不用关心垃圾回收器的选型。因为垃圾回收器的改变带来的性能提升几乎可以忽略。
然而,在大流量高并发场景下,如果一分钟出现1次或者多次ygc的话,那么我们评估使用场景,选择合适的垃圾回收器就显得更有价值。
另外,其实在实际应用过程中很少会出现fgc的情况,即使大流量的服务,基本都是在执行ygc,有时候可能几天才会出现一次fgc甚至很久都不出现。而且,线上活跃的应用一般都会持续迭代,可能3/5天上线一次,每次服务发布,之前积压的内存就清理了,几乎不会触发fgc

2. 对比

接下来我们对比一下上述三种搭配的适用场景:

2.1 parallel scavenge+ parallel old

启动参数:-XX:+UseParallelGC(新生代)和 -XX:+UseParallelOldGC(老年代),一般默认,不用手动配置。

特点:

多线程并行回收新生代(Parallel Scavenge)和老年代(Parallel Old)。
默认以最大化吞吐量(应用运行时间占比)为目标。
适合多核服务器环境,但对延迟敏感的应用可能不友好。

适用场景:后台计算密集型任务(如批处理),不追求低延迟。

实战示例:8C16G机器

-Xms8192m
-Xmx8192m
-XX:MaxMetaspaceSize=512m
-XX:MetaspaceSize=512m
-XX:MaxDirectMemorySize=1024m
-XX:ConcGCThreads=4
-XX:ParallelGCThreads=8
-Xmn4096m
-XX:CICompilerCount=3
-XX:+UnlockExperimentalVMOptions
-XX:+ParallelRefProcEnabled
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationStoppedTime
-Xloggc:/export/Logs/xxx/gc.log
-XX:GCLogFileSize=1024M
-XX:+HeapDumpAfterFullGC
-XX:HeapDumpPath=/export/Logs/xxx/fgcdump.log

2.2 parnew + cms

启动参数:-XX:+UseConcMarkSweepGC,需要手动配置,同时还需要其他参数,后文列出。

特点:

老年代使用并发标记清除算法,尽量减少停顿时间。
新生代默认使用ParNew回收器(多线程)。
通过并发标记减少STW时间,但存在内存碎片问题。
注意:Java 8中仍可用,但在后续版本(Java 9+)被标记为废弃(Deprecated),最终在Java 14中被移除。

适用场景:对延迟敏感的中大型应用(如Web服务)。
搭配参数:

参数含义示例
-XX:ParallelGCThreads并行GC线程的数量(ncpu <= 8 : ParallelGCThreads = ncpus,ncpu > 8 : 8 + (ncpus - 8) ( 5/8 ))-XX:ParallelGCThreads=8
-XX:+UseParNewGC年轻代使用ParNew-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC老年代使用CMS-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabledJVM会在CMS的并发标记阶段(Concurrent Marking Phase)触发类卸载,释放不再使用的类元数据占用的内存-XX:+CMSClassUnloadingEnabled
-XX:+UseCMSInitiatingOccupancyOnly只用设定的回收阈值,如果不指定,JVM仅在第一次使用设定值,后续则自动调整-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction老年代允许的最大使用率,达到则触发old gc-XX:CMSInitiatingOccupancyFraction=75
-XX:+CMSParallelRemarkEnabled在CMS GC前启动一次ygc,目的在于减少old gen对ygc gen的引用,降低remark时的开销,一般CMS的GC耗时 80%都在remark阶段-XX:+CMSParallelRemarkEnabled
-XX:CICompilerCount热点编译器线程数(2 + int(max(0, cpu_core_num - 2) * 0.25)最低2核,超出2核的部分拿出25%来热点编译)-XX:CICompilerCount=3
-XX:ConcGCThreadsCMS下是(ParallelGCThreads + 3) / 4 向下取整, G1下是ParallelGCThreads / 4-XX:ConcGCThreads=4

实战示例:8C16G机器

-Xms8192m
-Xmx8192m
-XX:MaxMetaspaceSize=512m
-XX:MetaspaceSize=512m
-XX:MaxDirectMemorySize=1024m
-XX:ConcGCThreads=4
-XX:ParallelGCThreads=8
-Xmn4096m
-XX:CICompilerCount=3
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+UnlockExperimentalVMOptions
-XX:+CMSClassUnloadingEnabled
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=75
-XX:+ExplicitGCInvokesConcurrent
-XX:+ParallelRefProcEnabled
-XX:+CMSParallelRemarkEnabled
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationStoppedTime
-Xloggc:/export/Logs/xxx/gc.log
-XX:GCLogFileSize=1024M
-XX:+HeapDumpAfterFullGC
-XX:HeapDumpPath=/export/Logs/xxx/fgcdump.log

2.3 g1

启动参数:-XX:+UseG1GC,需要手动配置,同时还需要其他参数,后文列出。

特点:

将堆划分为多个区域(Region),优先回收垃圾最多的区域。
可预测的停顿时间模型,支持大堆(数十GB到上百GB)。
混合了标记-整理和复制算法,减少内存碎片。
注意:Java 7u4引入,Java 9+成为默认回收器。

适用场景:需要平衡吞吐量和延迟的大型应用(如企业级服务)。
搭配参数(cms体系中描述过的这里不再赘述,见示例):

参数含义示例
-XX:+UseG1GC使用G1垃圾回收器-XX:+UseParNewGC
-XX:MaxGCPauseMillis设置 G1 的暂停时间目标。这会告诉 G1 试图将 GC 暂停时间控制在指定的毫秒数内-XX:MaxGCPauseMillis=50
-XX:G1HeapRegionSize设置 G1 的堆区域大小。堆被划分为多个区域(Region),G1 GC 在这些区域上进行垃圾收集。设置合适的区域大小可以帮助提高垃圾回收效率。()-XX:G1HeapRegionSize=16m

实战示例:8C16G机器

-Xms8192m
-Xmx8192m
-XX:MaxMetaspaceSize=512m
-XX:MetaspaceSize=512m
-XX:MaxDirectMemorySize=1024m
-Xmn4096m
-XX:ConcGCThreads=2
-XX:ParallelGCThreads=8
-XX:CICompilerCount=3
-XX:+UseG1GC
-XX:MaxGCPauseMillis=50
-XX:+UnlockExperimentalVMOptions
-XX:+ParallelRefProcEnabled
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationStoppedTime
-Xloggc:/export/Logs/xxx/gc.log
-XX:GCLogFileSize=1024M
-XX:+HeapDumpAfterFullGC
-XX:HeapDumpPath=/export/Logs/xxx/fgcdump.log

3. 总结

后台计算密集型任务(如批处理),不追求低延迟。场景下使用默认配置,即parallel scavenge + parallel old。对延迟敏感的中大型应用(如Web服务)使用parnew + cms。需要平衡吞吐量和延迟的大型应用(如企业级服务)使用g1。
C端高并发应用优先考虑parnew + cms 或 g1,但具体的选型还需根据实际场景评估,如果很难评估的情况下,可以同分组内A B两台机器,上线后观察分析gc日志以及在流量高峰期的cpu表现。


http://www.niftyadmin.cn/n/5868134.html

相关文章

axios几种请求类型的格式

Axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;广泛用于浏览器和 Node.js 中发送 HTTP 请求。它支持多种请求格式&#xff0c;包括 GET、POST、PUT、DELETE 等。也叫RESTful 目录 一、axios几种请求类型的格式 1、get请求 2、post请求 3、put请求 4、delete请求 二…

JAVA【微服务】Spring AI 使用详解

目录 一、前言二、Spring AI 概述2.1 什么是 Spring AI2.2 Spring AI 特点2.3 Spring AI 带来的便利2.4 Spring AI 应用领域2.4.1 聊天模型2.4.2 文本到图像模型2.4.3 音频转文本2.4.4 嵌入大模型使用2.4.5 矢量数据库支持2.4.6 数据工程 ETL 框架三、Spring AI 对接 ChatGPT3.…

JavaScript的BOM编程

BOM编程 what 通过JS代码操作浏览器&#xff0c;js的编程就是面向对象编程&#xff0c;最多的就是面向标签对象编程 BOM:Browser Object Model 浏览器对象模型&#xff0c;以window对象为依托&#xff0c;表示浏览器窗口以及页面可见区域。 学习BOM操作&#xff0c;就是学习…

【DeepSeek系列】05 DeepSeek核心算法改进点总结

文章目录 一、DeepSeek概要二、4个重要改进点2.1 多头潜在注意力2.2 混合专家模型MoE2.3 多Token预测3.4 GRPO强化学习策略 三、2个重要思考3.1 大规模强化学习3.2 蒸馏方法&#xff1a;小模型也可以很强大 一、DeepSeek概要 2024年&#xff5e;2025年初&#xff0c;DeepSeek …

ROS 2机器人开发--话题通信实战--制作一个可视化系统状态监听工具

1 准备工作 2 自定义通信接口 3 系统信息获取与发布 4 测试QT 5 数据可视化显示 1 准备工作 需求分析&#xff1a;开发一个基于ROS 2话题通信的系统状态监听工具&#xff0c;能够实时获取系统&#xff08;如CPU、内存、网络等&#xff09;的运行状态&#xff0c;并通过可视…

powershell:报错npm : 无法加载文件 D:\develop\nodejs\npm.ps1,因为在此系统上禁止运行脚本

问题 原因分析 由于 ​PowerShell 的执行策略&#xff08;Execution Policy&#xff09;​​ 限制导致的。Windows 系统默认禁止运行未签名的脚本&#xff08;包括 npm 脚本&#xff09;&#xff0c;因此运行 npm run dev 时&#xff0c;PowerShell 阻止了脚本的执行。 解决…

玩转Docker | 使用Docker部署IT-tools工具箱

玩转Docker | 使用Docker部署IT-tools工具箱 前言一、 IT-tools介绍简介主要特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署IT-tools服务下载镜像创建容器检查容器状态检查服务端口安全设置四、访问IT-tools应用五、测试与使用六、总结前言 在信息技…

Maven 依赖的深入理解(二)

四、Maven 依赖传递原理 &#xff08;一&#xff09;传递依赖的概念 在 Maven 项目中&#xff0c;传递依赖是一个非常重要的特性。它指的是当项目引入一个依赖时&#xff0c;这个依赖所依赖的其他组件库也会被 Maven 自动引入到项目中&#xff0c;而无需我们在项目的pom.xml文…