前言

在Java开发中,垃圾收集器的选择对系统性能有着致命的影响。Java 8后,虽然G1 GC成为默认,但是它在延迟性控制上仍有限。ZGC作为最新一代高性能低延迟垃圾收集器,解决了CMS和G1在延迟、垃圾堆容量和吞吐量方面的重大突破。本文将完整给出ZGC的技术原理和实际应用,帮助您做出最适合应用场景的GC选型。


Java中的垃圾收集概述

垃圾收集的意义

Java采用自动内存管理(GC),帮助开发者自动处理不再使用的对象内存。GC的目标是在尽量减少延迟的同时,回收无用对象,维持系统的稳定运行和内存调度。

当前垃圾收集系统培胜于 "根集" 分析,根集为程序可达对象的集合,GC进行探游,找出可达对象,其余则可以处理成垃圾。

Java堆内存分区

Java堆内存通常分为两大区域:

  • Young Generation (年轻代):新生成的对象,较简单。内部分为Eden和Survivor S0/S1。

  • Old Generation (老年代):清除尽Young GC后仍然存活的对象,常应用于Full GC。

有些GC器同时使用总缓存(Metaspace)、堆外内存区域、选择性老年代等特殊区域。


Java垃圾收集器的演进

在深入了解ZGC之前,我们需要先回顾Java中垃圾收集器的发展历程,特别是ZGC推出之前在Java 8及更早版本中常见的几种GC方式。这不仅帮助我们理解ZGC为何而生,也为我们提供比较其优劣的视角。

Java 8中的主要垃圾收集器

Java 8中默认的垃圾收集器是Parallel GC,但在很多中大型项目中,开发者常常会根据不同的业务需求切换为CMS(Concurrent Mark-Sweep)或者G1(Garbage First)。下面我们来分别了解这些GC方式的基本特点与运行机制。

1. Serial GC

适用于单核处理器或者内存较小的客户端应用。

  • 特点:串行执行,GC过程中STW(Stop-The-World)时间较长。

  • 优点:实现简单,适用于内存小、线程少的环境。

  • 缺点:不适合服务器端或多线程环境。

// 启用Serial GC
java -XX:+UseSerialGC -Xms512m -Xmx512m MyApp
2. Parallel GC(吞吐量优先GC)

也称为吞吐量GC,追求最大程度的吞吐量,适用于批处理和计算密集型任务。

  • 特点:多个GC线程并行执行,仍会发生Stop-The-World。

  • 优点:高吞吐、GC时间相对较短。

  • 缺点:GC期间程序线程全部暂停。

// 启用Parallel GC
java -XX:+UseParallelGC -Xms1g -Xmx1g MyApp
3. CMS GC(并发标记清除)

目标是减少GC对程序运行的影响,引入并发阶段。

  • 特点:多阶段GC流程,包括初始标记、并发标记、重新标记、并发清除。

  • 优点:在标记和清除阶段大部分操作可并发,适合响应时间敏感型应用。

  • 缺点:内存碎片化严重,标记过程复杂。

// 启用CMS GC
java -XX:+UseConcMarkSweepGC -Xms2g -Xmx2g MyApp
4. G1 GC(Garbage First)

G1是在Java 8中被引入并逐渐替代CMS的收集器,强调可预测的停顿时间

  • 特点:堆被分成多个小区域(Region),混合收集老年代和年轻代。

  • 优点:减少Full GC频率,支持大内存,延迟控制能力较CMS强。

  • 缺点:在低延迟场景仍有不可预测的长时间停顿。

// 启用G1 GC
java -XX:+UseG1GC -Xms4g -Xmx4g MyApp

各GC对比总结

GC 类型并发能力停顿时间吞吐量内存使用效率是否碎片整理
Serial
Parallel中等
CMS低(有碎片)
G1中到低

从上表中可以看出,虽然CMS和G1 GC在延迟方面取得了一定进展,但仍存在以下痛点:

  1. Full GC影响严重:尤其是在老年代清理时,仍需STW,造成业务请求中断。

  2. 大堆内存支持不佳:CMS在大堆场景(数十GB以上)容易产生碎片,甚至OOM。

  3. 标记和清理效率有限:并发过程开销大,回收速度不够理想。

因此,为了进一步降低延迟、提升大内存环境下的GC性能,ZGC应运而生,尤其在Java 11之后成为低延迟场景的新宠。


ZGC概述

ZGC(Z Garbage Collector)是Java平台自Java 11起引入的一种可扩展、低延迟、并发型垃圾收集器,旨在为大堆内存场景下的Java应用提供极低的GC暂停时间(最大不超过10ms),同时保持高吞吐量。

在ZGC出现前,虽然G1 GC已实现了对延迟控制的初步优化,但在某些实时性要求极高的系统中(如金融撮合引擎、大型电商、在线游戏服务器等),它仍然无法完全满足毫秒级停顿时间的需求。ZGC正是为此类场景设计。

核心目标

ZGC的主要设计目标如下:

  • 暂停时间不超过10ms(与堆大小无关)

  • 支持超大堆内存(最大支持16TB)

  • 并发回收、并发压缩

  • 低吞吐量损失

  • 低内存碎片率

这些特性使得ZGC非常适用于以下应用场景:

  • 低延迟应用(例如在线交易系统)

  • 大型数据处理(大内存服务端)

  • 响应时间敏感的分布式系统

Java版本支持情况

ZGC最早以实验性功能形式在JDK 11中引入,之后不断发展完善:

Java 版本状态启用方式
JDK 11实验性-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
JDK 15正式支持-XX:+UseZGC
JDK 17长期支持(LTS)-XX:+UseZGC
JDK 21引入Generational ZGC-XX:+UseZGC(自动使用代际ZGC)

注意:ZGC不支持Java 8。在JDK 8中,建议使用G1 GC作为替代方案来控制延迟,但G1在最小停顿时间方面远不如ZGC。

如何启用ZGC

在JDK 11中启用ZGC需显式解锁实验性选项:

java \-XX:+UnlockExperimentalVMOptions \-XX:+UseZGC \-Xmx8g \-Xms8g \-jar myapp.jar

从JDK 15起,ZGC已成为正式功能,无需再解锁实验性选项:

java \-XX:+UseZGC \-Xmx16g \-Xms16g \-jar myapp.jar

建议在中大型内存(如4GB以上)下使用ZGC以体现其优势。

ZGC命名的由来

ZGC中的"Z"并没有官方明确解释,但社区中普遍认为其含义为:

  • Zero Pause GC(零停顿GC)

  • 或者表示最终GC的终极目标(The last GC you'll ever need)


ZGC架构深度分析

ZGC之所以能够实现低于10ms的暂停时间,离不开其创新性的内部架构设计。ZGC彻底颠覆了以往垃圾收集器在内存布局和对象访问上的方式,采用以下关键技术:

  • 区域化堆(Region-based Heap)

  • 彩色指针(Colored Pointers)

  • 加载屏障(Load Barriers)

  • 并发回收机制

本节将逐一详细讲解这些核心模块。本部分为第一部分,重点解析:

1. 区域化堆(Region-based Heap)

传统GC如CMS和Parallel GC使用固定大小的堆区域分代(如Eden区、Survivor区、Old区),但ZGC则摒弃了这种固定代分区方式,采用区域化(Region-based)堆布局

ZGC的堆被动态划分成一块块的逻辑小区域(region),每个区域最小为2MB,最大可以根据配置扩展。这些区域根据用途被分类如下:

  • Small Object Space:存储小对象,一般小于256KB。

  • Large Object Space:存储大对象,单个对象跨多个区域。

  • Remapped Space:用于搬迁中的对象区域(relocation)。

ZGC的region是非连续、非固定映射的,具有以下优势:

  • 堆可动态增长和收缩,极大提升内存使用弹性。

  • 对不同区域类型可采用不同的压缩或回收策略。

  • 支持并发搬迁与并发压缩,减少碎片和延迟。

示例:

// 模拟大对象分配时,ZGC自动从 Large Object Space 中分配区域
byte[] largeArray = new byte[10 * 1024 * 1024]; // 10MB 数组

ZGC可快速在Large Object Space中定位空闲Region,支持高并发申请。

2. 彩色指针(Colored Pointers)

ZGC使用的一项革命性技术是彩色指针,即将对象引用的高位用于标记GC状态信息。这种做法打破了传统将引用与元数据分离的限制。

ZGC的对象指针是64位,但由于现代操作系统通常只用低48位寻址,ZGC利用高位中的几位嵌入颜色信息:

位段含义
0-47实际地址
48Finalizable标记位
49Remapped标记位
50Marked标记位
51Load Barrier位

通过这种设计,ZGC可以在访问对象指针的瞬间就获知其GC状态,而无需查找外部元数据结构,大大提升了并发访问的性能。

优点包括:

  • 减少GC元信息结构依赖

  • 提升GC期间并发可达性分析速度

  • 降低堆碎片率和对象搬迁时的同步成本

示例说明:

Object ref = obj; // ref 实际上是带颜色标记的指针

开发者无需干预,ZGC自动对这些指针做屏障处理和位标记解码。

3. 加载屏障(Load Barrier)

**加载屏障(Load Barrier)**是ZGC最独特的技术之一。它在每次访问Java对象引用时自动触发,用于处理对象在搬迁过程中的一致性问题。

加载屏障的主要职责是:

  • 判断引用对象是否已被搬迁(relocated)

  • 如果是,执行指针修复(pointer remapping)

  • 保证所有线程访问到的是最新的对象地址

ZGC加载屏障是在JVM层面插入的,对开发者完全透明,不需要修改应用代码。其实现通常依赖CPU原语(如内存屏障)结合内联汇编,实现高效的指针判断与更新。

加载屏障的逻辑类似如下伪代码:

Object ref = load(o);
if (ref has relocation flag) {ref = remap(ref);
}
return ref;

优势

  • 极低延迟:加载屏障可与普通对象访问融合,不增加明显开销

  • 并发友好:允许对象在不暂停应用线程的前提下完成搬迁

  • 精确控制:每次读取都能精准判断是否需要修复

真实案例场景

List<Person> people = ...;
for (Person p : people) {// 访问 p.getName() 时会触发 Load Barrier 检查其对象是否已搬迁System.out.println(p.getName());
}

即使此时ZGC正在并发地搬迁 Person 对象,也不会阻塞当前线程读取。

4. 并发回收机制

ZGC之所以能将GC暂停控制在10ms以内,根本在于其极致的并发垃圾回收机制。它几乎将所有GC阶段转为并发执行,避免了传统GC中长时间的"Stop-The-World"。

ZGC的垃圾回收周期包含如下阶段:

阶段是否并发描述
初始标记(Pause Mark Start)极短暂停,标记GC Root
并发标记(Concurrent Mark)并发遍历整个堆,标记存活对象
并发重定位准备(Concurrent Prepare Relocate)选择要搬迁的对象
暂停重定位开始(Pause Relocate Start)短暂停,开启重定位
并发搬迁(Concurrent Relocate)将活跃对象搬迁至新区域
并发重映射(Concurrent Remap)更新所有引用为新地址(结合Load Barrier)

其中,两个短暂停阶段(初始标记与重定位开始)通常耗时都小于2ms。

ZGC的设计核心是将搬迁(对象复制)也并发完成,这在传统GC中几乎是不可想象的。

示例流程图(文字描述)

  1. GC线程开始并发标记阶段,与应用线程并行运行。

  2. 找到垃圾对象集合后,选择部分区域进行回收。

  3. 搬迁对象至新区域,由多个线程协作完成,应用线程继续运行。

  4. 通过加载屏障和指针重映射,确保应用访问到的是新地址。

这种模式极大减少了STW(Stop-The-World)对应用性能的影响。

优势总结

  • 几乎全程并发执行

  • 极低暂停时间(<10ms)

  • 支持TB级堆空间的低延迟回收

  • 精细控制搬迁单元,避免大块复制阻塞


ZGC工作原理

ZGC的基本目标是在实现大内存空间支持下,并俗降低GC暂停时间,尽量将GC各阶段转为并发执行。下面将以ZGC一次完整GC周期为线程,分段解析其工作流程:

1. GC触发

ZGC与其他GC一样,通过内存占用分析来触发GC。其GC触发可能原因包括:

  • 内存占用超过阀值

  • 对象分配失败

  • 手动调用 System.gc()

在GC触发后,ZGC进入一次完整的GC周期。

2. 初始标记 (Pause Mark Start)

这是ZGC兩个短暂停阶段之一,将GC Root(如程序栈、静态对象、JNI指针) 加入标记集合。

特点:

  • 更新系统中所有根引用

  • 更新开始标记的标志位(带有颜色的指针)

  • 优化後通常耗时<1ms

3. 并发标记 (Concurrent Mark)

将基于标记集合的引用给所有可达对象进行并发添加。此阶段与应用程序同时运行,不需要暂停。

内部机制:

  • 利用带颜色指针判定对象是否已标记

  • 培子线程分布标记任务,支持核心级并发

  • 并行识别、合并图结构

// 类似于每个对象被标记为活跃时,就会追踪其引用
if (!isMarked(obj)) {mark(obj);for (Object ref : obj.getReferences()) {mark(ref);}
}

4. 并发转移准备 (Concurrent Prepare Relocate)

此阶段分析哪些Region需要转移,通常选择废物比例高的Region,尽量减少拷贝量,提高性能。

  • 标记结束后,定义要移动的Region集合

  • 与应用程序并行

5. 移动开始暂停 (Pause Relocate Start)

为了保证移动阶段的一致性,需要简短地暂停一下,切换GC状态,启用转移。

  • 暂停平均耗时也很短(<2ms)

  • 进行新的Region空间创建

6. 并发对象移动 (Concurrent Relocate)

ZGC使用并发线程将活跃对象转移到新的Region。这些操作与应用程序同时进行,合作Load Barrier确保引用不算错。

// Load Barrier检测到指针已移动
if (isForwarded(ptr)) {ptr = loadForwardingPointer(ptr); // 修复指针
}

7. 并发重映 (Concurrent Remap)

在应用运行过程中,某些指针可能还未被修复,此阶段将通过并发线程把还未被更新的指针重新映射。

  • 重映是指针修复的最后阶段

  • 确保所有引用指向正确对象

8. GC结束

当所有移动完成、指针已更新后,GC周期结束,释放被固定重映的老Region,新Region补入。


ZGC与Java 8中垃圾收集器的对比

在Java 8中,常用的几种垃圾收集器包括Serial GC、Parallel GC、CMS(Concurrent Mark-Sweep)以及G1(Garbage First)GC。这些收集器在当时各有优劣,而ZGC自Java 11引入后,彻底改变了GC在延迟敏感场景下的表现。本节将ZGC与Java 8时代代表性的垃圾收集器——G1、CMS等进行对比,从多个维度全面展示ZGC的优势与局限。

1. 暂停时间对比

收集器暂停类型最佳暂停时间典型暂停时间最差暂停时间
SerialStop-the-World10ms - 数百ms数十ms - 秒级秒级
ParallelStop-the-World数十ms数百ms数秒
CMS并发标记 + STW几十ms数百ms可能超过1s(碎片整理)
G1分区化,部分并发低于200ms(可设定)50ms - 200ms秒级(Full GC)
ZGC几乎全并发<1ms<10ms通常不超过10ms

ZGC的暂停时间控制极其优秀,甚至在TB级堆上依然稳定控制在10ms以内。

2. 吞吐量与堆规模支持

收集器最大支持堆大小吞吐能力
Serial小于8GB较低
Parallel几十GB
CMS通常推荐<100GB中高
G1理论上可到数百GB中高(根据Region粒度变化)
ZGC实际支持高达数TB高(并发、分层)

ZGC特别适用于超大堆应用,如大数据平台、实时分析引擎、AI在线推理服务等。

3. 并发能力

收集器并发标记并发清理/压缩对应用线程干扰
Serial
Parallel
CMS部分并发
G1否(压缩是STW)
ZGC是(全阶段并发)极低

ZGC是真正意义上"全阶段并发"的垃圾收集器,大幅减小GC对响应时间的干扰。

4. 内存碎片处理

  • CMS 是非压缩的,容易出现内存碎片,导致分配失败。

  • G1 虽然分区化,但压缩仍需STW,内存整理成本高。

  • ZGC 利用并发搬迁机制,可以在线完成对象压缩,极少碎片产生。

// G1碎片整理常常需要Stop-the-World:
-XX:+UseG1GC
-XX:+G1HeapRegionSize=8m
// 遇到Old区不足可能引发 Full GC 暂停

5. 部署与兼容性

收集器Java版本支持启用方式
CMSJava 8 - Java 14(后移除)-XX:+UseConcMarkSweepGC
G1Java 7+默认GC(Java 9+)
ZGCJava 11+(JDK 15转为生产)
-XX:+UnlockExperimentalVMOptions
-XX:+UseZGC
``` |ZGC从JDK 15起被标记为生产可用,推荐用于延迟敏感、堆空间巨大的现代系统。### 6. 代码透明度与可维护性ZGC对开发者完全透明,不需要特殊编码配合,不影响业务逻辑。```java
public class User {private String name;private Address address;
}// 正常使用,不需要关注GC过程:
User u = new User();
u.setName("张三");

相比之下,CMS可能因碎片化或过时参数带来配置难度,而G1对GC参数的调优要求较高。


总结:为何选ZGC?

ZGC在以下场景中极具优势:

  • 低延迟要求:如金融交易撮合系统、在线推荐、游戏服务端

  • 大内存平台:如TB级堆数据仓库、机器学习推理服务、海量会话保持

  • 高并发业务:如大型API网关、消息中间件

同时,ZGC的易用性(代码透明、自动压缩、稳定暂停时间)也大大降低了运维与开发门槛,是Java未来GC的核心发展方向之一。


ZGC性能调优指南

ZGC虽然拥有优秀的默认性能表现,但在特定业务场景中,通过合理调优可以进一步提升其效率,降低资源占用,增强服务稳定性。本节将围绕ZGC的参数设置、性能监控、常见问题应对策略进行系统讲解。

一、ZGC启用与基础配置

ZGC需Java 11及以上版本支持,启用ZGC基本参数如下:

# 启用ZGC(Java 11中仍为实验特性)
-XX:+UnlockExperimentalVMOptions
-XX:+UseZGC# 示例:设置最大堆、初始堆大小
-Xmx16g
-Xms16g

在JDK 15及以上版本,无需再解锁实验选项,可直接使用 -XX:+UseZGC

二、核心调优参数解析

1. 堆空间设置

ZGC不像G1那样依赖分区大小调优,它的核心是Region自动管理。因此主要关注以下两个参数:

-Xmx16g   # 最大堆内存
-Xms16g   # 初始堆内存

建议:ZGC在大堆(如>8G)下性能更优,最好将 -Xmx 与 -Xms 设为相同,避免运行时堆调整。

2. GC线程数控制
-XX:ConcGCThreads=N       # 控制并发GC线程数量
-XX:ParallelGCThreads=N   # 初始标记和对象拷贝时的并行线程数

ZGC自动选择线程数,但在高并发系统中,如需控制资源消耗可手动设定。

3. 启用 NUMA 感知(多核性能优化)
-XX:+UseNUMA

在多Socket架构服务器上建议启用,提升跨节点堆访问性能。

4. 禁用透明大页(降低TLB抖动)
-XX:+UseTransparentHugePages=false

可避免ZGC在大型对象分配中引发频繁页表转换开销。

三、ZGC特有诊断与追踪参数

ZGC支持详细的垃圾回收日志输出,有助于观察其行为与性能:

-Xlog:gc*,safepoint:file=gc.log:time,uptime,level,tags

样例输出:

[2.344s][info][gc,start] GC(0) Pause Mark Start
[2.344s][info][gc] GC(0) Pause Mark Start 0.415ms
[2.345s][info][gc,start] GC(0) Concurrent Mark
[2.567s][info][gc] GC(0) Concurrent Mark 222.187ms
...

通过这些日志,可判断暂停时间是否稳定,GC是否频繁触发等信息。

四、常见调优策略

场景调优建议
吞吐不足提升GC线程数,增加CPU核心数
GC频繁检查内存是否足够,提升 -Xmx 值
暂停波动大检查是否开启了大页,是否存在频繁Full GC
CPU占用高适当限制 GC 并发线程数
堆未满就GC检查是否被显式调用 System.gc(),避免误触发

五、结合容器环境的参数配置建议

在Kubernetes、Docker等容器中运行时,应注意:

-XX:+UseContainerSupport   # 启用容器资源感知(JDK 10+ 默认开启)
-XX:MaxRAMPercentage=80.0  # 最大可用内存占比(替代传统的 -Xmx)

这样可确保ZGC在容器内合理管理资源,不会溢出宿主机。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91729.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91729.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/91729.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机“十万个为什么”之跨域

计算机“十万个为什么”之跨域 本文是计算机“十万个为什么”系列的第五篇&#xff0c;主要是介绍跨域的相关知识。 作者&#xff1a;无限大 推荐阅读时间&#xff1a;10 分钟 一、引言&#xff1a;为什么会有跨域这个“拦路虎”&#xff1f; 想象你正在参观一座戒备森严的城堡…

C语言:20250719笔记

字符数组在C语言中&#xff0c;支持字符串常量&#xff0c;不支持字符串变量。如果想要实现类似的字符串变量&#xff0c;C语言提供了两种实现方式&#xff1a;字符数组&#xff1a;char name[] “哪吒”&#xff1b;字符指针&#xff1a;char *name "娜吒"&#x…

decltype是什么,什么作用?

基本概念decltype 是 C11 引入的关键字&#xff0c;用于推导表达式的类型&#xff0c;且会完整保留类型的细节&#xff08;包括 const、引用 &、指针 * 等&#xff09;。语法:decltype(表达式) 变量名核心特点1.推导依据是表达式本身&#xff0c;而非表达式的结果&#xff…

RPC 与 Feign 的区别笔记

一、基本概念 1.1 RPC&#xff08;Remote Procedure Call&#xff09; 定义&#xff1a;远程过程调用&#xff0c;允许像调用本地方法一样调用远程服务的方法。 本质&#xff1a;跨进程通信&#xff0c;隐藏了底层网络通信的复杂性。 常见实现&#xff1a; Java 原生 RMIDub…

高防IP能够防御CC攻击吗?它具备哪些显著优势?

摘要&#xff1a; 面对日益复杂的网络攻击&#xff0c;高防IP作为重要的安全工具&#xff0c;不仅能防御常见的DDoS攻击&#xff0c;还能有效应对CC攻击。本文将解析高防IP防御CC攻击的原理及其核心优势&#xff0c;帮助读者了解其在网络安全中的关键作用。一、高防IP能否防御C…

TypeScript 类型注解(一)

一、TypeScript 类型注解1、什么是TpyeScript类型注解- 是否还记得TypeScript的两个重要特性&#xff1f;- 类型系统、适用于任何规模- 可以说&#xff0c;TS的类型系统是TS最重要的功能&#xff1b;那么什么是类型注解呢&#xff1f;其实就是在声明变量时&#xff0c;将变量的…

弗兰肯斯坦式的人工智能与GTM策略的崩溃

2025 年上半年已经明确了一件事&#xff1a;B2B 市场营销团队被工具淹没&#xff0c;但缺乏策略。人工智能无处不在。收入领导者在进行无休止的试点。营销团队拼凑各种点解决方案&#xff0c;希望能实现规模扩张。然而&#xff0c;销售线索的增长停滞不前。信誉正在受损。曾经承…

NAND闪存(NAND Flash)是什么?

NAND闪存(NAND Flash)是什么? NAND闪存(NAND Flash)详解 NAND闪存是一种非易失性存储介质(断电不丢失数据),广泛应用于SSD、U盘、手机存储等设备中。NAND Flash 的全称是 “Negative-AND Flash”(与非型闪存),其名称源自其底层存储单元的电路结构——基于**“与非门…

Android性能优化之UI渲染优化

一、UI渲染核心瓶颈深度解析 1. 渲染管线关键阶段阶段CPU工作GPU工作潜在卡顿点Measure计算View尺寸-嵌套布局多次测量Layout计算View位置-频繁重排(Relayout)Draw构建DisplayList指令集-复杂自定义View.onDraw()Sync & Upload资源上传到GPU内存纹理上传大图/未压缩资源Ras…

基于Spring AI Alibaba的智能知识助手系统:从零到一的RAG实战开发

&#x1f4d6; 项目概述 在人工智能快速发展的今天&#xff0c;RAG&#xff08;Retrieval-Augmented Generation&#xff09;技术已成为构建智能问答系统的核心技术。本文将详细介绍一个基于Spring AI Alibaba DashScope深度集成的智能知识助手系统的完整开发过程&#xff0c;…

VirtualBox + CentOS:启用 DHCP 获取 IPv4 地址

标题&#xff1a; VirtualBox CentOS&#xff1a;启用 DHCP 获取 IPv4 地址 日期&#xff1a; 2025-07-18 一、问题现象 最小化安装的 CentOS 7 虚拟机里敲&#xff1a; ip addr输出只有 lo 的 127.0.0.1 以及 enp0s3 的 IPv6 链路本地地址&#xff0c;没有 IPv4&#xff0…

Git

Git简介Git 是一个分布式版本控制工具&#xff0c;通常用来对软件开发过程中的源代码文件进行管理。通过Git 仓库来存储和管理这些文件&#xff0c;Git 仓库分为两种:本地仓库:开发人员自己电脑上的 Git仓库。远程仓库:远程服务器上的 Git 仓库。commit: 提交, 将本地文件和版本…

通信算法之294:LTE系统中的整数倍频偏估计

在LTE系统中&#xff0c;整数倍频偏估计主要通过以下方法实现&#xff1a;一、最大似然估计法&#xff08;ML&#xff09;通过遍历预设的整数倍频偏范围&#xff08;如30kHz&#xff09;&#xff0c;将接收信号与本地的PSS序列在不同频偏点上进行相关运算&#xff0c;选择相关峰…

数字人直播:开启直播行业新纪元​

​原始尺寸更换图片p9-flow-imagex-sign.byteimg.com​​在科技日新月异的当下&#xff0c;直播行业正经历着一场深刻变革&#xff0c;数字人直播的兴起&#xff0c;宛如一颗璀璨新星&#xff0c;照亮了直播领域的新征程。数字人直播&#xff0c;是利用先进的人工智能技术&…

朝鲜升级供应链恶意软件XORIndex,再次瞄准npm生态系统

Socket威胁研究团队最新披露&#xff0c;朝鲜国家支持的黑客组织在"传染性面试"攻击活动中采用了新型恶意软件加载器XORIndex&#xff0c;该恶意程序专门通过npm软件包注册表渗透软件供应链。攻击规模与持续性此次攻击并非孤立事件&#xff0c;而是针对开发者、求职者…

Windows 下 VS2019 编译 libevent-2.1.10 库

1. 你需要VS2019 编译好openssl-1.1.1 &#xff0c;这个具体编译或者下载可以参考我的博客openssl生成的库是这两个文件接下来&#xff0c;打开CMake &#xff0c;主要是下面的需要设置好最后Config Generate即可&#xff1b;全部成功生成 22个然后INSTALL右键生成 最后看下生…

Vim多列操作指南

我们在使用 Vim 时&#xff0c;经常需要同时编辑多个文件&#xff0c;或者同一个文件的不同部分。Vim 提供了分割窗口&#xff08;split&#xff09;和垂直分割窗口&#xff08;vsplit&#xff09;的功能&#xff0c;允许我们在同一个 Vim 会话中查看多个缓冲区&#xff08;buf…

Python网络爬虫实现selenium对百度识图二次开发以及批量保存Excel

一.百度识图自动上传图片from selenium import webdriver from selenium.webdriver.edge.options import Options from selenium.webdriver.common.by import By edge_options Options() edge_options.binary_location r"C:\Program Files (x86)\Microsoft\Edge\Applica…

Vue中的refs字段使用记录

这段代码是 Vue.js 中结合 Element UI 等 UI 库的典型表单验证写法&#xff0c;具体含义如下&#xff1a;代码拆解 this.$refs.fromData.validate((valid) > {// 验证后的回调逻辑 })this.$refs.fromData $refs 是 Vue 提供的特殊属性&#xff0c;用于访问模板中通过 ref&qu…

多方案对比分析:后端数据加密策略及实践

多方案对比分析&#xff1a;后端数据加密策略及实践 随着互联网业务对用户隐私和数据安全的要求不断提升&#xff0c;后端系统中对敏感数据的加密保护已成为必备需求。从对称加密、非对称加密到数据库透明加密、应用层字段加密&#xff0c;各种方案各有特点。本文将以方案对比分…