当前位置: 首页 > news >正文

Java 垃圾回收机制(GC)概览

简介

Java垃圾收集、堆和运行时编译器默认选择

  • jdk1.9开始,默认使用G1收集器,
  • GC Threads的最大数量受堆大小和可用CPU资源限制
  • 初始堆大小为物理内存的1/64
  • 最大堆大小为物理内存的1/4
  • 分层编译器,同时使用C1和C2

JVM 垃圾收集器可以为配置优先满足两个目标之一:最大暂停时间(maximum pause-time) 和应用程序吞吐量(application throughput)

  • 最大暂停时间:通过-XX:MaxGCPauseMillis= 指定,垃圾收集器会调整 Java 堆大小和其他与垃圾收集相关的参数,以试图使垃圾收集暂停时间短于毫秒。最大暂停时间目标的默认值因收集器而异。这些调整可能会导致垃圾收集更频繁地发生,从而降低应用程序的整体吞吐量。但在某些情况下,无法满足所需的暂停时间目标。

  • 吞吐量目标:吞吐量目标是通过收集垃圾所花费的时间来衡量的,垃圾收集之外所花费的时间就是应用程序时间。通过-XX:GCTimeRatio=nnn指定垃圾收集时间与申请时间之比为1/(1+nnn)。例如,-XX:GCTimeRatio=19设定垃圾收集总时间的 1/20 或 5% 为目标。

几种GC类型

  • 串行收集器(Serial Collector):单线程收集,适用于单核处理器,无法利用多处理器硬件。启用参数:-XX:+UseSerialGC
  • 并行收集器(Parallel Collector):也称为吞吐量收集器(jdk8默认收集器) 区别于串行收集器主要具有多线程,启用参数:-XX:+UseParallelGC
  • CMS(并发标记清除)收集器:适用于响应时间比吞吐量重要,要求较短GC暂停时间并能与垃圾收集共享处理器资源的应用程序。启用参数:-XX:+UseConcMarkSweepGC。从JDK9开始,CMS收集器已被弃用,并使用G1代替。
  • G1收集器:Garbage-First (G1),此收集器旨在从小型机器扩展到具有大量内存的大型多处理器机器。它能够以高概率满足暂停时间目标,同时实现高吞吐量。从JDK9开始,G1为默认收集器。启用参数:-XX:+UseG1GC
  • ZGC:ZGC 提供的最大暂停时间不到一毫秒,但会牺牲一些吞吐量。它适用于需要低延迟的应用程序,ZGC 适用于从几百兆字节到 16TB 的堆大小。从 JDK 11 开始,ZGC 作为一项实验性功能推出。启用参数:-XX:+UseZGC

如何选择GC

  • 如果应用程序的数据集较小(最多约 100 MB),则选择带有选项的串行收集器-XX:+UseSerialGC。
  • 如果应用程序将在单个处理器上运行并且没有暂停时间要求,则选择带有选项的串行收集器-XX:+UseSerialGC。
  • 如果 (a) 应用程序的峰值性能是第一优先级,并且 (b) 没有暂停时间要求或者可以接受一秒或更长时间的暂停,那么让 VM 选择收集器或选择并行收集器-XX:+UseParallelGC。
  • 如果响应时间比总体吞吐量更重要,并且垃圾收集暂停必须保持更短,那么请选择最并发的收集器-XX:+UseG1GC(jdk8以上)或CMS(8以下)。
  • 如果响应时间是高优先级,那么选择一个完全并发的收集器 -XX:+UseZGC。

G1 GC

G1 旨在使用当前的目标应用程序和环境在延迟和吞吐量之间实现最佳平衡,其特性包括:

  • 适用于堆大小高达数十 GB 或更大,其中 50% 以上的 Java 堆被实时数据占用。
  • 适用于对象分配和提升的速度可能会随着时间的推移而发生很大变化。
  • 适用于堆内存中存在大量碎片的应用。G1通过整理存活对象来减少碎片。
  • 可预测的暂停时间目标不超过几百毫秒,避免长时间的垃圾收集暂停。

G1 主要通过对象迁移(Evacuation)来回收空间:在选定的要收集的内存区域内找到的存活对象被复制到新的内存区域,并在过程中对其进行压缩。迁移完成后,先前被存活对象占用的空间将被重新用于应用程序的分配。

G1堆布局

G1将堆划分为一组相等的heap regions,region是内存分配和回收的基本单位。region可以是空的(浅灰色),或者分配给年轻代(红色)或老年代(蓝色)。年轻代包含Eden区(红色)和survivor区(红色带s),对于跨多个区域的对象,老生代区域可能非常大(浅蓝带s)

在这里插入图片描述

G1回收阶段

  • Concurrent Start(并发启动) 在 Concurrent Start 阶段,G1 会并发标记老年代的存活对象,并进行正常的年轻代回收(Normal Young Collection)
  • Remark(标记完成阶段):当并发标记阶段结束后,G1 会暂停应用线程执行 Remark 阶段。这一阶段会完成标记,确保所有存活对象都被标记,并进行一些额外的处理,如类卸载、引用处理等。
  • Cleanup(清理阶段):这个阶段的主要目的是完成空间回收准备工作,判断是否会执行 Space-Reclamation 阶段。
  • Space-Reclamation Phase(空间回收阶段):此阶段由多个年轻代收集组成,除了年轻代区域外,还会回收老生代区域的存活对象, 这些收集也称为 Mixed Collections(混合回收)。
  • Full GC(完全垃圾回收):如果在 G1 回收过程中,G1 在收集活跃对象的过程中发生了内存不足的情况,它将执行 Full GC

SATB Snapshot-At-The-Beginning (开始快照)

SATB是一种垃圾回收标记算法,常用于 并发垃圾回收器 ,特别是在 G1 和 ZGC 等收集器中。
它的目的是解决并发标记阶段中,如何处理在标记过程中可能会修改的对象引用的问题。SATB 是一种 并发标记算法,在标记开始时通过记录一个“快照”,确保在标记过程中,即使有对象的引用发生变化,也能保证准确的标记结果。

Remembered Set

Remembered Set 是一种用于垃圾回收的数据结构,特别在 G1 GC 和 其他分代垃圾回收器(如 CMS)中使用,用来优化 跨代引用 的处理。它的主要作用是帮助 标记 和 回收 阶段处理 年轻代(Young Generation)和 老年代(Old Generation)之间的引用,减少跨代引用带来的性能问题。

Collection Set

Collection Set 是一个集合,它记录了在当前垃圾回收周期中需要被回收的区域。这些区域通常是存放了 垃圾对象 或 跨代引用 的区域。根据垃圾回收的类型和阶段,Collection Set 可以包括 年轻代 或 老年代 的区域,或者两者的组合。

G1参数

  • -XX:-G1UseAdaptiveIHOP 这个参数用于 禁用 G1 的自适应 IHOP 调整机制。默认情况下,G1 收集器会根据堆的使用情况自动调整 Initiating Heap Occupancy Percentage(IHOP) 的值。自适应 IHOP 允许 G1 根据实际运行时的内存使用情况,动态调整触发混合回收的堆占用阈值。

  • -XX:InitiatingHeapOccupancyPercent 这个参数用于 设置触发混合回收(Mixed GC)的阈值,即 老年代堆空间的使用比例。它表示 当老年代堆的使用比例达到该值时,G1 将启动混合垃圾回收。

  • -XX:G1PeriodicGCInterval 周期性全堆回收的时间间隔,使得 G1 收集器能够定期执行 全堆垃圾回收(Full GC),默认为0,意味着不会执行周期性全堆回收

  • -XX:MaxGCPauseMillis=200 最大暂停时间目标,默认200ms

G1 建议避免使用像-Xmn 或 -XX:NewRatio 这样的选项来限制年轻代的大小。年轻代的大小是 G1控制停顿时间的主要手段之一。如果将年轻代的大小固定为某个特定值,可能会限制 G1 的灵活性,使其无法有效地调整以满足设定的停顿时间目标。

ZGC

Z 垃圾收集器(ZGC)是一种可扩展的低延迟并发垃圾收集器。ZGC 可同时执行所有高成本工作,且不会使应用程序线程的执行停止超过一毫秒。它适用于需要低延迟的应用程序。暂停时间与正在使用的堆大小无关。ZGC 适用于从几百兆字节到 16TB 的堆大小。

配置 ZGC 使用大页面通常会带来更好的性能(就吞吐量、延迟和启动时间而言),并且没有真正的缺点,只是设置起来稍微复杂一些。设置过程通常需要 root 权限,这就是为什么默认情况下不启用它的原因。

在 Linux x86 上,大页面(也称为“巨页”)的大小为 2MB。

配置系统的大页池以拥有所需的页面数量(需要root权限):
echo 9216 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

其他事项

引用类型

  • Strong References(强引用):普通的对象引用都是强引用,只要有强引用指向某个对象,垃圾回收器不会回收该对象。
  • Soft References(软引用): 软引用与弱引用类似,都是用来引用不应该被强制持有的对象。不同之处在于,只有在内存不足时,软引用所指向的对象才会被回收。因此,它们适合用于缓存,尤其是当我们希望尽量保留缓存但又不影响程序的内存使用时。
  • Weak References(弱引用) :弱引用是一种不强制保持对象存在的引用。当垃圾回收器运行时,如果一个对象只被弱引用引用,它将被回收。弱引用通常用于缓存或可以被回收的对象。
  • Phantom References(虚引用):虚引用是最弱的引用类型。与弱引用和软引用不同,虚引用并不会影响对象的生命周期。当一个对象只被虚引用引用时,它仍然可以被垃圾回收。虚引用最大的作用是提供一种机制,在对象被回收时得到通知。虚引用通常与引用队列结合使用。

The Cleaner API

Finalization 在 JDK 9 中已被弃用,并在JDK18中已被删除。
如果需要关闭资源可以使用,try-with-Resources或Cleaner API(jdk9引入)

使用场景

与 try-with-resources 不同,Cleaner 可以用于那些不能在构造时立即进行清理的对象。在对象被垃圾回收后,Cleaner 将会执行指定的清理代码。

  1. 复杂生命周期场景:当对象的使用与其清理之间的关系非常复杂时,Cleaner 可以帮助管理这些清理任务。例如,管理一个需要在多个地方使用但必须确保最终被正确关闭的资源。
  2. 非显式资源释放:在某些情况下,资源的释放可能并不在单一位置完成。这时,使用 Cleaner 可以确保在对象被回收时自动释放资源。
  3. 作为对象的清理回调:当对象完成其用途后,Cleaner 可以被注册为清理操作的回调,而不必依赖于用户代码来执行清理。

Cleaner API核心方法

  • create():创建一个Cleaner对象,并启动一条新线程用于监听目标对象是否已经被回收。
  • register(Object obj, Runnable task):注册一个需要被清理的对象和一个清理任务。当对象被垃圾回收器回收时,清理任务将被执行。

Cleaner示例

import java.lang.ref.Cleaner;public class CleanerExample {// This Cleaner is shared by all CleanerExample instancesprivate static final Cleaner CLEANER = Cleaner.create();private final State state;public CleanerExample(String id) {state = new State(id);CLEANER.register(this, state);}// Cleaning action class for CleanerExampleprivate static class State implements Runnable {final private String id;private State(String id) {this.id = id;System.out.println("Created cleaning action for " + this.id);}//对象不可达时,run方法将被调用@Overridepublic void run() {System.out.println("Cleaner garbage collected " + this.id);}}public static void main(String[] args) {CleanerExample myObject1 = new CleanerExample("myObject1");// Make myObject1 unreachablemyObject1 = null;System.out.println("-- Give the GC a chance to schedule the Cleaner --");for (int i = 0; i < 100; i++) {// Calling System.gc() in a loop is usually sufficient to trigger// cleanup in a small program like this.System.gc();try {Thread.sleep(1);} catch (InterruptedException e) {}}System.out.println("-- Finished --");}
}

文章来源:https://docs.oracle.com/en/java/javase/23/gctuning/introduction-garbage-collection-tuning.html

相关文章:

Java 垃圾回收机制(GC)概览

简介 Java垃圾收集、堆和运行时编译器默认选择 jdk1.9开始&#xff0c;默认使用G1收集器&#xff0c;GC Threads的最大数量受堆大小和可用CPU资源限制初始堆大小为物理内存的1/64最大堆大小为物理内存的1/4分层编译器&#xff0c;同时使用C1和C2 JVM 垃圾收集器可以为配置优…...

Kafka节点服役和退役

1 服役新节点 1&#xff09;新节点准备 &#xff08;1&#xff09;关闭 bigdata03&#xff0c;进行一个快照&#xff0c;并右键执行克隆操作。 &#xff08;2&#xff09;开启 bigdata04&#xff0c;并修改 IP 地址。 vi /etc/sysconfig/network-scripts/ifcfg-ens33修改完…...

Git如何简单使用

文章目录 GitGitlabGitLab和GitHub有什么区别?Gitlab简单使用Gitlab常用指令Git Git是一个分布式版本控制系统。 它用于记录文件的修改历史,方便多人协作开发软件等项目。例如一个软件开发团队,成员们会频繁修改代码,Git可以追踪每个人的修改内容、时间等信息。 主要功能…...

酒水分销积分商城小程序开发方案php+uniapp

酒水分销积分商城小程序开发&#xff0c;开发语言后端php&#xff0c;前端uniapp。核心功能模块&#xff1a;酒水商城、积分商城、二级分销、抽奖、优惠券。可以二开或定制。协助部署搭建。...

MTU-内核态(数据链路层或网络接口上能够传输的最大数据包大小)

MTU&#xff08;最大传输单元&#xff0c;Maximum Transmission Unit&#xff09;是网络中用于表示数据链路层或网络接口上能够传输的最大数据包大小。 1. 工作原理 MTU 决定了一个数据包&#xff08;包括头部和数据部分&#xff09;的最大长度。它影响到数据的传输&#xff…...

React的基础API介绍(一)

目录 useEffect1. 替代生命周期方法2. 副作用管理3. 依赖项数组4. 多次使用5. 与闭包配合6. 支持异步操作7. 减少样板代码 注意事项useEffetct是如何拿到变量count最新的值&#xff1f;1. 每次渲染都会创建新的函数作用域2. 闭包捕获最新的状态值3. useEffect 的执行时机 useLa…...

【Electron】总结:如何创建Electron+Element Plus的项目

我将结合官网手册与AI问到的信息&#xff0c;直接给出步骤&#xff0c;与命令。 一、准备环境 首先在C盘Users&#xff0c;你的登录的账号名文件夹下&#xff0c;编辑.npmrc文件。添加镜像地址。 如果使用了yarn&#xff0c;则是.yarnrc。可以全部都配置。 npm install -g …...

从依托指标字典到 NoETL 自动化指标平台,指标口径一致性管理的进阶

今天&#xff0c;我们一起来梳理和盘点下不同代际指标平台如何实现指标口径一致性管理&#xff1a; 第一代&#xff1a;指标口径登记与管理 第一代指标平台聚焦于指标口径的登记与管理&#xff0c;依托指标字典实现企业指标口径的有效检索与管理功能。 此阶段&#xff0c;业…...

嵌入式面试题练习 - 2024/11/15

欢迎找我进行职业规划&#xff0c;超值的自我投资 -> 嵌入式软件工程师一对一指导 1.设有定义char *p[]{"Shanghai","Beijing","Honkong"};则结果为j字符的表达式是&#xff08;&#xff09; A *p[1] 3 B *(p[1] 3) C *(p[3] 1) D p[3] […...

分析http话术异常挂断原因

用户反馈在与机器人通话时&#xff0c;自己明明有说话&#xff0c;但是通话还是被挂断了&#xff0c;想知道原因。 分析日志 我们根据用户提供的freeswitch日志分析&#xff1a;发现是因为超时导致话术执行hangup动作&#xff0c;结束了通话。 从这一行向上分析日志&#xff…...

云岚到家 秒杀抢购

目录 秒杀抢购业务特点 常用技术方案 抢券 抢券界面 进行抢券 我的优惠券列表 活动查询 系统设计 活动查询分析 活动查询界面显示了哪些数据&#xff1f; 面向高并发如何提高活动查询性能&#xff1f; 如何保证缓存一致性&#xff1f; 数据流 Redis数据结构设计 如…...

【WPF】Prism库学习(一)

Prism介绍 1. Prism框架概述&#xff1a; Prism是一个用于构建松耦合、可维护和可测试的XAML应用程序的框架。它支持WPF、.NET MAUI、Uno Platform和Xamarin Forms等多个平台。对于每个平台&#xff0c;Prism都有单独的发布版本&#xff0c;并且它们在不同的时间线上独立开发。…...

0 -vscode搭建python环境教程参考(windows)

引用一篇非常详细的vscode搭建python环境教程 链接&#xff1a;vscode安装以及配置Python基本环境 以下是VSCode和PyCharm的对比 个人更建议使用VSCode Visual Studio Code (VSCode) Visual Studio Code 是由微软开发的一款免费、开源的轻量级代码编辑器。它支持多种编程语…...

Uniapp 引入 Android aar 包 和 Android 离线打包

需求&#xff1a; 原生安卓 apk 要求嵌入到 uniapp 中&#xff0c;并通过 uniapp 前端调起 app 的相关组件。 下面手把手教你&#xff0c;从 apk 到 aar&#xff0c;以及打包冲突到如何运行&#xff0c;期间我所遇到的问题都会 一 一 进行说明&#xff0c;相关版本以我文章内为…...

10款高效音频剪辑工具,让声音编辑更上一层楼。

音频剪辑在音频&#xff0c;视频&#xff0c;广告制作&#xff0c;游戏开发&#xff0c;广播等领域中都有广泛的应用。通过音频剪辑&#xff0c;创作者可以通将不同的音频片段进行剪切、拼接、混音等操作&#xff0c;创作出风格各异的音乐作品。如果你也正在为音频创作而努力的…...

Javascript——设计模式(一)

Javascript常见设计模式-CSDN博客 设计模式专栏内容总结-CSDN博客 C#编程思想——设计模式-CSDN博客 设计模式概述及其作用 设计模式&#xff08;Design Pattern&#xff09;是一套被反复使用、多数人知晓的、经过分类编目的代码设计经验的总结。使用设计模式的主要目的是为…...

Hybird和WebView

在移动端Hybrid开发模式下&#xff0c;iOS和Android应用都可以通过一种共享代码的方式&#xff0c;利用Web技术&#xff08;HTML、CSS、JavaScript&#xff09;和原生应用的功能进行开发。这种方式的主要优点是减少了开发成本&#xff0c;因为大部分代码可以共享&#xff0c;同…...

c++实现中缀表达式 转换为后缀表达式

使用栈来计算后缀表达式的值&#xff1a; 9(3 - 1)*310/2; 后缀表达式&#xff1a;所有的符号都是在运算数字的后面出现&#xff1a; 9 3 1 – 3 * 10 2 / 规则: 中缀表达式转后缀表达式: 1.从左到右遍历中缀表达式的每个数字和符号&#xff0c;若是数字就打印同时入栈数…...

Cisco FMC重置SmartLicense到Evaluatin mode步骤

1 科普&#xff1a; what is FMC full name is Firepower Management Center, 是思科FirePower防火墙的统一管理平台. 能管理ASA不&#xff1f; no&#xff0c;只能管理FTD模式的墙。这里的FTD包括物理机firepower系列运行的FTD&#xff0c;以及FTDv&#xff08;虚拟化版本&a…...

多表查询综合归纳

目录 1. 多表关系 1.1 一对多&#xff08;多对一&#xff09; 1.2 多对多 1.3 一对一 2. 多表查询概述 2.1 熟悉表 2.2 笛卡尔积 2.3 消除笛卡尔积 2.4 多表查询分类 3. 内连接 3.1 隐式内连接 3.2 显式内连接 4. 外连接 4.1 左外连接 4.2 右外连接 5. 自连接 …...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...