JVM 垃圾回收机制和GC案例分析

news2024/11/15 19:49:09

1. 引言

Java 虚拟机(JVM)的垃圾回收(Garbage Collection, GC)机制,是自动内存管理的重要组成部分。它通过回收不再使用的对象,避免手动释放内存的麻烦。然而,随着系统复杂性的增加,GC 的效率对应用性能影响极大,特别是在电商交易系统中,GC 的延迟或频繁触发可能会导致系统响应时间变慢,影响用户体验。

本篇文章将深入探讨 JVM 的垃圾回收机制,重点介绍 年轻代老年代 的对象转化过程,常见的 垃圾回收器,以及如何在 Linux 系统中分析 Java 应用的 GC 过程,解决常见的 GC 问题。

2. JVM 垃圾回收模型概述

JVM 的内存结构分为两个主要区域:年轻代(Young Generation)老年代(Old Generation)。年轻代中对象生命周期较短,老年代中对象生命周期较长。JVM 的垃圾回收器通过分代回收策略,分别处理不同代中的对象。

2.1 年轻代(Young Generation)

年轻代存储新创建的对象,它又进一步划分为:

  • Eden 区:所有新创建的对象首先分配在 Eden 区。
  • Survivor 区:包括两个 Survivor 区,S0 和 S1,用于在 Minor GC 时保存存活的对象。

2.2 老年代(Old Generation)

当对象在年轻代中存活足够长时间,或者年轻代空间不足时,这些对象会被移到老年代。老年代主要存储生命周期较长的对象。

2.3 永久代/元空间

永久代(PermGen)存储类元数据,JDK 8 之后,永久代被元空间(Metaspace)替代。

3. 年轻代与老年代的对象转化过程

在 JVM 中,对象的生命周期管理基于“分代假说”,即大多数对象的生命周期都很短,少部分对象存活时间较长。基于这一假设,JVM 采用了年轻代与老年代的分代回收机制。

3.1 年轻代的对象分配

当使用 new 创建对象时,JVM 将对象分配到 Eden 区。若 Eden 区满,则会触发 Minor GC,GC 会检查存活的对象并将它们移到 Survivor 区。每次 Minor GC 后,存活的对象会在 S0 和 S1 之间来回交换。当对象在 Survivor 区存活到一定次数(达到 年龄阈值),就会被提升到老年代。

// 电商系统中的订单对象分配
Order newOrder = new Order();  // 新对象创建,存储在 Eden 区
3.2 从年轻代到老年代的晋升

当一个对象存活过多次 Minor GC 后,JVM 会将其从 Survivor 区提升到 老年代。老年代中的对象生命周期更长,回收频率较低。

在这里插入图片描述

3.3 垃圾回收的分代策略

年轻代对象的生命周期短、创建频繁,JVM 通过快速回收策略处理。老年代则存放生命周期较长的对象,垃圾回收发生频率低,但回收时间较长。Minor GC 主要清理年轻代,而 Major GC(或 Full GC) 则回收整个堆(包括年轻代和老年代)。

4. 常见垃圾回收器及其原理

JVM 提供了多种垃圾回收器,适用于不同的应用场景。下面是几种常见的垃圾回收器及其适用场景。

4.1 Serial GC

Serial GC 是最简单的垃圾回收器,适用于单线程环境。它会暂停所有应用线程,串行执行 GC,回收年轻代和老年代。

  • 优点:实现简单,适用于单线程应用。
  • 缺点:在多线程环境下表现较差,暂停时间较长。
# 使用 Serial GC
java -XX:+UseSerialGC -jar ecommerce-system.jar

4.2 Parallel GC

Parallel GC 是默认的多线程垃圾回收器,适用于多核 CPU 环境。它并行地执行 Minor GC,尽可能减少垃圾回收的时间开销。

  • 优点:适用于 CPU 密集型应用,吞吐量高。
  • 缺点:在 GC 过程中,应用仍会暂停。
# 使用 Parallel GC
java -XX:+UseParallelGC -jar ecommerce-system.jar

4.3 CMS(Concurrent Mark-Sweep)GC

CMS GC 是一种低延迟的垃圾回收器,专注于减少老年代的回收时间。它通过并发标记和清理,尽量避免应用长时间停顿。

  • 优点:减少老年代 GC 的停顿时间,适合低延迟应用。
  • 缺点:对 CPU 资源的消耗较高,可能会出现“浮动垃圾”问题。
# 使用 CMS GC
java -XX:+UseConcMarkSweepGC -jar ecommerce-system.jar

4.4 G1 GC

G1 GC 是适用于大堆内存的垃圾回收器,它通过划分堆内存为多个区域(Region),并根据回收的价值优先回收最大的区域。G1 GC 结合了并行和并发的优势,能够提供可预测的停顿时间。

  • 优点:适合大内存低延迟应用,能够提供可配置的最大停顿时间。
  • 缺点:实现复杂,对性能调优要求较高。
# 使用 G1 GC
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar ecommerce-system.jar
4.5 ZGC 和 Shenandoah GC

ZGCShenandoah GC 是近年来推出的超低延迟垃圾回收器。它们的目标是将 GC 停顿时间控制在 10ms 以内,适合需要极低延迟的应用场景。

# 使用 ZGC
java -XX:+UseZGC -jar ecommerce-system.jar

5. 在 Linux 系统中分析 GC 日志

在生产环境或性能测试中,分析 JVM 的垃圾回收日志可以帮助我们识别内存管理的瓶颈,从而优化应用程序性能。通过 GC 日志,我们能够了解垃圾回收器的运行情况,识别频繁的 Full GC 或 Minor GC,以及分析 GC 的停顿时间、对象分配和晋升情况等。

5.1 启用 GC 日志

首先,我们需要启用 GC 日志功能,通过以下 JVM 参数可以记录详细的 GC 日志:

java -Xlog:gc*:file=gc.log:time,tags -jar ecommerce-system.jar

这些参数的含义如下:

  • -Xlog:gc*:启用 GC 日志记录。
  • file=gc.log:将 GC 日志输出到指定文件 gc.log 中。
  • time,tags:添加时间戳和 GC 事件标签,方便后续分析。

5.2 常用 GC 日志选项

在生产环境中,除了基础的 GC 日志记录,还可以启用更细粒度的日志,帮助分析性能问题。常见的 GC 日志选项如下:

# 打印GC详细信息,包括停顿时间、回收内存大小等
java -Xlog:gc*:gc.log:time,uptime,level,tags
  • time:显示绝对时间戳。
  • uptime:显示从 JVM 启动到当前的时间。
  • level:记录日志的级别(如 info、debug)。
  • tags:显示日志类别(如 GC 类型、阶段)。

5.3 GC 日志结构

GC 日志的典型输出结构如下:

[2024-09-14T12:00:00.123+0000][gc,start       ] GC(0) Pause Young (G1 Evacuation Pause) (young) 10M->5M(50M) 30ms
[2024-09-14T12:00:00.153+0000][gc,end         ] GC(0) Pause Young (G1 Evacuation Pause) (young) 30ms
[2024-09-14T12:01:01.567+0000][gc,start       ] GC(1) Pause Full (G1 Full GC) 40M->20M(100M) 250ms
[2024-09-14T12:01:01.817+0000][gc,end         ] GC(1) Pause Full (G1 Full GC) 250ms

日志内容解释:

  • GC 类型Pause Young 表示年轻代 GC,Pause Full 表示 Full GC。
  • 内存变动:如 10M->5M(50M),表示 GC 前年轻代占用 10MB,GC 后剩余 5MB,总共 50MB 可用内存。
  • GC 耗时:GC 操作耗时,如 30ms 表示 GC 操作耗时 30 毫秒。

6. 性能测试中的 GC 分析

在性能测试中,GC 的频繁触发或长时间停顿会影响应用的响应速度和吞吐量。以下是一些常见的 GC 问题及其分析思路:

6.1 问题:频繁的 Minor GC

在性能测试中,若观察到频繁的 Minor GC,通常表示年轻代内存分配过于频繁,可能是因为系统频繁创建短生命周期的对象,导致 Eden 区被快速填满。

日志示例
[2024-09-14T12:05:00.123+0000][gc,start       ] GC(10) Pause Young (G1 Evacuation Pause) 40M->20M(60M) 25ms
[2024-09-14T12:05:05.123+0000][gc,start       ] GC(11) Pause Young (G1 Evacuation Pause) 45M->25M(60M) 30ms
解决方式
  • 增加年轻代空间:通过增加 Eden 区或 Survivor 区的大小,减少 Minor GC 频率。可以通过 -XX:NewRatio-Xmn 参数调整年轻代的大小。

    java -Xms512m -Xmx2g -Xmn512m -jar ecommerce-system.jar
    
  • 对象分配优化:如果 GC 频繁触发,检查系统是否存在频繁创建临时对象的情况,可以通过对象池减少对象的创建与销毁。

优化后日志

通过调整后,可以观察到 Minor GC 频率的降低:

[2024-09-14T12:10:00.123+0000][gc,start       ] GC(12) Pause Young (G1 Evacuation Pause) 40M->20M(80M) 20ms
[2024-09-14T12:15:00.123+0000][gc,start       ] GC(13) Pause Young (G1 Evacuation Pause) 45M->25M(80M) 22ms

6.2 问题:频繁的 Full GC

Full GC 会暂停整个应用线程,对系统性能影响较大。如果日志中出现频繁的 Full GC,说明老年代空间不足,或对象晋升到老年代过多。

日志示例
[2024-09-14T12:20:01.567+0000][gc,start       ] GC(20) Pause Full (G1 Full GC) 200M->150M(300M) 500ms
[2024-09-14T12:22:01.567+0000][gc,start       ] GC(21) Pause Full (G1 Full GC) 220M->180M(300M) 600ms
解决方式
  • 增加老年代空间:可以通过增加老年代的空间来减少 Full GC 的触发。使用 -Xmx 参数增加堆内存大小。

    java -Xms1g -Xmx4g -jar ecommerce-system.jar
    
  • 选择合适的垃圾回收器:在低延迟需求的系统中,考虑使用 G1 GCZGC 代替传统的 Parallel GC 或 CMS GC,以减少 Full GC 的停顿时间。

    java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar ecommerce-system.jar
    
优化后日志

通过增加堆内存或使用合适的垃圾回收器,Full GC 的频率会大幅降低:

[2024-09-14T12:30:00.123+0000][gc,start       ] GC(22) Pause Full (G1 Full GC) 150M->100M(400M) 250ms
[2024-09-14T12:35:00.123+0000][gc,start       ] GC(23) Pause Full (G1 Full GC) 170M->120M(400M) 270ms

6.3 问题:长时间 GC 停顿

长时间的 GC 停顿会影响应用的响应时间,通常与老年代的垃圾回收耗时过长有关。为了减少 GC 停顿时间,可以选择合适的垃圾回收器,并优化 GC 参数。

日志示例
[2024-09-14T12:45:00.123+0000][gc,start       ] GC(30) Pause Full (G1 Full GC) 500ms
[2024-09-14T12:55:00.123+0000][gc,start       ] GC(31) Pause Full (G1 Full GC) 600ms
解决方式
  • 使用 G1 GC 或 ZGC:这些低停顿的垃圾回收器能够有效减少 GC 停顿时间。

    java -XX:+UseZGC -jar ecommerce-system.jar
    
  • 调优 GC 参数:在 G1 GC 中,-XX:MaxGCPauseMillis 可以帮助控制最大 GC 停顿时间。

    java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar ecommerce-system.jar
    
优化后日志

通过调整垃圾回收器,GC 停顿时间会明显减少:

[2024-09-14T13:00:00.123+0000][gc,start       ] GC(32) Pause Full (G1 Full GC) 250ms

7. 使用 GC 分析工具

在分析 GC 日志时,使用专业的分析工具可以大大提高效率,尤其是面对复杂的 GC 行为和大量的日志数据时,手动分析可能会耗费大量时间和精力。一个热门且功能强大的开源工具是 GCViewer,它可以将 GC 日志进行可视化,帮助我们更直观地分析和优化 JVM 的垃圾回收行为。

7.1 介绍 GCViewer

GCViewer 是一个开源的 GC 日志分析工具,支持多种类型的 JVM 垃圾回收器,包括 G1、CMS、Parallel、ZGC 等。它可以将 GC 日志中的事件、停顿时间、内存使用情况等可视化,并生成详细的报告,帮助开发者快速定位 GC 问题。

GCViewer 的主要功能包括:

  • GC 停顿时间的可视化:可以直观地看到每次 GC 事件的停顿时间。
  • 内存使用趋势分析:展示堆内存和非堆内存的使用趋势,帮助识别内存泄漏或分配不合理的问题。
  • GC 事件统计:提供 GC 次数、总时间、平均时间等详细的统计信息。
  • 生成报告:可以导出详细的 GC 分析报告,方便调优。

7.2 下载和安装 GCViewer

要使用 GCViewer,首先需要从其 GitHub 仓库下载源代码或预编译的 JAR 文件。

下载 GCViewer:

  1. 访问 GCViewer GitHub 仓库。
  2. 下载最新的 gcviewer-*.jar 文件。

7.3 使用 GCViewer 进行 GC 日志分析

以下是使用 GCViewer 分析 GC 日志的具体步骤:

步骤 1:生成 GC 日志

在启动 Java 应用程序时,确保已经启用了 GC 日志记录功能。例如,使用以下 JVM 参数启动你的电商交易系统应用,并生成 GC 日志文件:

java -Xlog:gc*:file=gc.log:time,tags -jar ecommerce-system.jar

步骤 2:打开 GCViewer

下载并安装 GCViewer 后,使用以下命令启动它:

java -jar gcviewer-1.36.jar

步骤 3:加载 GC 日志

启动 GCViewer 后,点击界面上的 File -> Open,然后选择你生成的 GC 日志文件 gc.log。GCViewer 会自动解析日志文件并展示出以下几项关键数据:

  • GC 停顿时间图:展示每次 GC 事件的停顿时间,帮助你发现可能导致系统性能下降的 Full GC 或长时间的 GC 停顿。
  • 堆内存使用情况图:显示年轻代和老年代的内存使用情况,便于分析对象在堆中的分配和晋升过程。
  • GC 事件统计:包括 Minor GC 和 Full GC 的次数、平均时间、最大时间等数据。

步骤 4:分析 GC 停顿时间

在 GCViewer 中,你可以直观地看到每次 GC 停顿时间的分布。下图展示了一个典型的 GCViewer 界面:

+------------------------------------+
|            GCViewer 图示            |
+------------------------------------+
|      |                             |
|  GC  |   GC 停顿时间 (ms)          |
|  图  |   ┌────────────────────┐   |
|      |   │ ●●●                 │   |
|      |   │    ●●●              │   |
|      |   │        ●●           │   |
|      |   └────────────────────┘   |
|------------------------------------|
|      |                             |
|  内  |   堆内存使用情况 (MB)      |
|  存  |   ┌────────────────────┐   |
|  图  |   │  ████               │   |
|      |   │        ████         │   |
|      |   │             ████    │   |
|      |   └────────────────────┘   |
+------------------------------------+

通过观察图中的 GC 停顿时间分布,能够快速发现哪些 GC 事件消耗了较长的时间。如果某次 Full GC 耗时明显过长,那么可能需要进一步优化老年代的内存分配,或考虑使用更高效的垃圾回收器(如 G1 或 ZGC)。

步骤 5:分析内存使用情况

在 GCViewer 中,还可以观察堆内存的使用情况,包括 Eden 区、Survivor 区和老年代的使用情况。通过这部分数据,可以判断对象是否过快地从年轻代晋升到老年代,或是否存在老年代内存不足导致的频繁 Full GC。

  • 如果 Eden 区频繁触发 Minor GC,可能需要调整年轻代的大小,使用参数 -Xmn-XX:NewRatio 进行优化。
  • 如果老年代频繁触发 Full GC,可能需要增加老年代的大小或调整晋升阈值,使用参数 -XX:MaxTenuringThreshold 或增加总堆内存 -Xmx

步骤 6:生成报告

GCViewer 还支持生成详细的报告,帮助你总结 GC 分析的结果。点击 File -> Export,可以将分析结果导出为 CSV 文件或图片格式,用于后续的性能优化和报告展示。

7.4 实例分析:电商交易系统的 GC 优化

假设你在测试一个电商交易系统时,发现系统在高并发情况下响应时间明显变慢。通过 GC 日志分析,发现系统频繁触发 Full GC,每次 GC 的停顿时间接近 500 毫秒,严重影响用户体验。

解决方案

  1. 通过 GCViewer,观察到老年代的使用率较高,很多对象过早晋升到老年代。
  2. 使用 -Xmx 增加堆内存大小,并调整年轻代和老年代的比例。
  3. 通过 -XX:MaxTenuringThreshold=10 参数,延迟对象晋升到老年代。
  4. 更换垃圾回收器,选择 G1 GC 以减少 Full GC 频率和停顿时间。

经过调整后,再次使用 GCViewer 分析 GC 日志,发现 Full GC 频率明显降低,停顿时间也减少至 200 毫秒以内,系统的整体响应速度得到提升。

8. 总结

垃圾回收机制在 JVM 中扮演着至关重要的角色,理解其原理和调优方法对于优化 Java 应用性能至关重要。通过深入分析 年轻代与老年代 的对象生命周期管理、不同 垃圾回收器 的工作机制以及在 Linux 系统中实际 GC 日志的分析,我们可以有效地解决电商交易系统中的性能瓶颈问题,提供更流畅的用户体验。

这篇文章从底层实现逻辑到 GC 日志的实际分析,展示了如何应对和解决 JVM 内存管理中的各种问题,帮助开发者在复杂的应用场景中做出正确的性能优化决策。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C/C++——野指针处理

在C++中,“野指针”(dangling pointer)指的是指向已释放或无效内存的指针。使用野指针可能导致程序崩溃或产生未定义行为。避免野指针的关键在于确保指针始终指向有效内存。下面是一些避免野指针的方法和最佳实践: 1、释放内存后置空指针 当释放掉分配的动态内存后,将指…

文本到3D生成

文本到3D生成是一种通过文本描述直接创建三维数字模型的技术。这种技术能够将语言描述转换成可视化的三维模型,使得内容创作者和设计师可以直接从概念阶段跳转到三维可视化,大大加快创作流程并提供更直观的设计和修改过程。 该技术的核心应用之一是基于…

【乐吾乐大屏可视化组态编辑器】使用手册

1 总览 开始设计:大屏可视化设计器 - 乐吾乐Le5le 1.1 画布 画布即绘画区域,将图形拖拽到画布进行编辑,绘制大屏。 1.2 菜单栏 顶部菜单导航,一级菜单可设置Logo、公司名称、文件编辑、常用编辑、查看、帮助,设置大…

MySQL篇(SQL - 分类)(持续更新迭代)

目录 简介 一、DDL 1. 简介 2. 数据库操作 2.1. 查库 查询所有数据库 查询当前数据库 2.2. 创库 2.3. 删库 2.4. 切库 3. 表操作 3.1. 查询 查询当前数据库所有表 查看指定表结构 查询指定表的建表语句 3.2. 创表 3.3. 改表 添加字段 修改数据类型 修改字段…

unity3d入门教程六

unity3d入门教程六 15.1预制体15.2编辑预制体15.3在场景中编辑15.4动态创建实例15.5实例的销毁16.1(练习)子弹发射16.2定时器16.3键盘事件 15.1预制体 火神山10天建成,使用了预制体技术 一个个小房间都是事先建造好的,最后吊车装…

Acrobat 2022 安装

软件介绍 Adobe Acrobat 是由Adobe公司开发的一款PDF(Portable Document Format,便携式文档格式)编辑软件。借助它,可以以PDF格式制作和保存文档,以便于浏览和打印,同时还可以使用一些高级工具来创建、编辑…

黑马十天精通MySQL知识点

一. MySQL概述 安装使用 MySQL安装完成之后,在系统启动时,会自动启动MySQL服务,无需手动启动。 也可以手动的通过指令启动停止,以管理员身份运行cmd,进入命令行执行如下指令: 1 、 net start mysql80…

Autosar E2E通信保护简介

文章目录 前言一、E2E基本概念二、为什么要做E2E?三、E2E保护的三种不同实现方式E2E TransformerE2E Protection Wrapper(E2EPW)COM E2E Callout四、E2E ProfileE2E Profile 01 机制E2E Profile 02 机制E2E Profile 04 机制E2E Profile 05 机制E2E Profile 06 机制E2E Profi…

828华为云征文|部署在线文件管理器 Spacedrive

828华为云征文|部署在线文件管理器 Spacedrive 一、Flexus云服务器X实例介绍1.1 云服务器介绍1.2 产品优势1.3 计费模式 二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 Spacedrive3.1 Spacedrive 介绍3.2 Docker 环境搭建3.3 Spac…

38900 机动车安全检测

参考文章:https://www.zhihu.com/question/458001000 机动车检查 《道路交通安全法实施条例》有关规定第十六条:机动车应当从注册登记之日起,按照下列期限进行安全技术检验: (一)营运载客汽车5年以内每年…

CSS 圆角渐变边框

<div class"contact-box"><div class"contact-item">联系我们</div> </div>.contact-item{width: 194px;height: 48px;border-radius: 20px 20px 20px 20px;background-color: #000000;color: #BDBDBD;font-weight: 500;font-size…

828华为云征文 | 华为云X实例服务器上部署知识图谱项目的详细指南

前言 知识图谱作为数据整合、语义分析和人工智能的重要基础&#xff0c;逐渐被广泛应用于各类领域。其通过结构化数据和关系映射&#xff0c;帮助用户更好地理解数据背后的意义。要成功构建和部署知识图谱项目&#xff0c;强大的计算资源和高效的存储查询能力至关重要。华为云X…

网易codeWave——新手如何使用多表头Excel导入数据

需求是需要将下面&#xff08;示例&#xff09;的多表头Excel表格&#xff0c;上传到服务器&#xff0c;展示在codeWave的表格组件内&#xff1a; 第一步下载官方插件&#xff1a; 可以先行查看文档再来 第二步&#xff1a; 选择一个上传组件 第三步&#xff0c;编写上传…

(1)LT9211学习笔记

文章目录 前言一、MIPI接口是什么&#xff1f;二、LT9211框图及应用1&#xff0c;作为MIPI发射机&#xff1a;2&#xff0c;作为双端口Lvds发射机3&#xff0c;作为TTL输出4&#xff0c;作为MIPI接收机&#xff1a;5&#xff0c;作为双端口Lvds接收机6&#xff0c;作为TTL输入 …

STM32(十三):通信协议——USART串口协议

通信接口 通信的目的&#xff1a;将一个设备的数据传送到另一个设备&#xff0c;扩展硬件系统。 通信协议&#xff1a;制定通信的规则&#xff0c;通信双方按照协议规则进行数据收发。 TX &#xff08;Transmit exchange&#xff09; 数据发送角 RX &#xff08;Receive ex…

GIS在线监测SF6密度微水传感器免焊接格兰头航插插头

概述 GIS&#xff08;气体绝缘金属封闭开关设备&#xff09;中的SF6&#xff08;六氟化硫&#xff09;气体密度微水传感器航插技术是指在GIS设备中安装SF6气体密度和微水传感器&#xff0c;以实现对SF6气体状态的在线监测。这些传感器能够实时监测SF6气体的密度、微水含量以及其…

通过SQL语句判断奇偶数的几种方法

文章目录 1. 准备数据2. 使用 % 判断奇偶数3. 使用 MOD 判断奇偶数4. 使用按位与运算符 & 1. 准备数据 假设我们有一张测试表test_numbers -- 创建测试表 CREATE TABLE test_numbers (number_value INT );-- 插入测试数据 INSERT INTO test_numbers (number_value) VALUE…

效率神器来了:AI工具手把手教你快速提升工作效能

随着科技的进步&#xff0c;AI工具已经成为提升工作效率的关键手段。本文将介绍一些实用的AI工具和方法&#xff0c;帮助你自动化繁琐的重复性任务、优化数据管理、促进团队协作与沟通&#xff0c;并提升决策质量。 背景&#xff1a;OOP AI-免费问答学习交流-GPT 自动化重复性任…

数论-快速幂

快速幂 模板代码推导过程 求 A^B mod C&#xff0c;时间复杂度 O(logB) 模板代码 using ll long long; // 可以在头文件中添加这行ll qmi(ll a, ll b, ll c) {ll ans 1; // 初始化结果为 1a % c; // 将 a 取模 c&#xff0c;确保 a 小于 cwhile (b) …

【chrony安装】安装chrony服务作为NTP客户端(linux版)

文章目录 前言一、介绍chrony二、安装前准备三、安装chrony3.1. 在线安装chrony3.2. 离线安装chrony 四、服务端配置4.1. 配置服务端4.1.1. 服务端4.1.2. 客户端 4.2. 设置开机自启 五、常用命令六、安装验证七、国内常用NTP服务器总结 前言 本文章主要介绍在Centos系统&#…