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

JVM垃圾回收笔记02-垃圾回收器

文章目录

  • 前言
  • 1.串行(Serial 收集器/Serial Old 收集器)
    • Serial 收集器
    • Serial Old 收集器
    • 相关参数
      • -XX:+UseSerialGC
  • 2.吞吐量优先(Parallel Scavenge 收集器/Parallel Old 收集器)
    • Parallel Scavenge 收集器
    • Parallel Old 收集器
    • 相关参数
      • -XX:+UseParallelGC ~ -XX:+UseParallelOldGC
      • -XX:+UseAdaptiveSizePolicy
      • -XX:GCTimeRatio=ratio
      • -XX:MaxGCPauseMillis=ms
      • -XX:ParallelGCThreads=n
  • 3.响应时间优先(ParNew 收集器/CMS 收集器)
    • CMS 收集器
    • 相关参数
      • -XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld
      • -XX:ParallelGCThreads=n ~ -XX:ConcGCThreads=threads
      • -XX:CMSInitiatingOccupancyFraction=percent
      • -XX:+CMSScavengeBeforeRemark
  • 4.G1(Garbage First收集器)
    • 前言
    • 介绍
    • G1 VS CMS
    • 1.Young Collection
    • 2.Young Collection + CM
    • 3.Mixed Collection
    • 4.Full GC
    • 5.Remark(重新标记阶段)
  • ZGC 收集器


前言

如果说回收(收集)算法是内存回收的方法论,那么垃圾回收(收集)器就是内存回收的具体实现。
虽然有各种的收集器,但并非要挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现,更加没有万能的垃圾收集器,我们能做的就是根据具体应用场景选择适合自己的垃圾收集器。试想一下:如果有一种四海之内、任何场景下都适用的完美收集器存在,那么我们的 HotSpot 虚拟机就不会实现那么多不同的垃圾收集器了。
JDK 默认垃圾收集器(使用 java -XX:+PrintCommandLineFlags -version 命令查看):

  • JDK 8: Parallel Scavenge(新生代)+ Parallel Old(老年代)
  • JDK 9 ~ JDK22: G1

1.串行(Serial 收集器/Serial Old 收集器)

Serial 收集器

Serial(串行)收集器是最基本、历史最悠久的垃圾收集器了。大家看名字就知道这个收集器是一个单线程收集器了。它的 “单线程” 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( “Stop The World” ),直到它收集结束。
新生代采用标记-复制算法,老年代采用标记-整理算法
在这里插入图片描述
因为Serial(串行)收集器出现的 Stop The World 带来的不良用户体验,所以在后续的垃圾收集器设计中停顿时间在不断缩短(仍然还有停顿,寻找最优秀的垃圾收集器的过程仍然在继续)。
Serial 收集器优点:它简单而高效(与其他收集器的单线程相比)。Serial 收集器由于没有线程交互的开销,自然可以获得很高的单线程收集效率。Serial 收集器对于运行在 Client 模式下的虚拟机来说是个不错的选择。

Serial Old 收集器

Serial 收集器的老年代版本,它同样是一个单线程收集器。它主要有两大用途:
一种用途是在 JDK1.5 以及以前的版本中与 Parallel Scavenge 收集器搭配使用,另一种用途是作为 CMS 收集器的后备方案。
在这里插入图片描述

相关参数

-XX:+UseSerialGC

-XX:+UseSerialGC 实际上是指定使用Serial(年轻代)和Serial Old(老年代)的组合。这种设置适合于数据量较小、对应用的停顿时间要求不高且资源受限(如CPU核心数量有限)的环境。

2.吞吐量优先(Parallel Scavenge 收集器/Parallel Old 收集器)

JDK1.8中默认使用收集器为Parallel Scavenge + Parallel Old收集器组合
使用 java -XX:+PrintCommandLineFlags -version 命令查看

-XX:InitialHeapSize=262921408 -XX:MaxHeapSize=4206742528 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)

JDK1.8 默认使用的是 Parallel Scavenge + Parallel Old,如果指定了-XX:+UseParallelGC 参数,则默认指定了-XX:+UseParallelOldGC,可以使用-XX:-UseParallelOldGC 来禁用该功能

Parallel Scavenge 收集器

Parallel Scavenge 收集器是使用标记-复制算法的多线程收集器,Parallel Scavenge 收集器关注点是吞吐量(高效率的利用 CPU)。CMS 等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。
所谓吞吐量就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值。
在这里插入图片描述
Parallel Scavenge 收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量,如果对于收集器运作不太了解,手工优化存在困难的时候,使用 Parallel Scavenge 收集器配合自适应调节策略,把内存管理优化交给虚拟机去完成也是一个不错的选择。
新生代采用标记-复制算法,老年代采用标记-整理算法
在这里插入图片描述

Parallel Old 收集器

Parallel Scavenge 收集器的老年代版本。使用多线程和“标记-整理”算法。在注重吞吐量以及 CPU 资源的场合,都可以优先考虑 Parallel Scavenge 收集器和 Parallel Old 收集器。
在这里插入图片描述

相关参数

-XX:+UseParallelGC ~ -XX:+UseParallelOldGC

解释:UseParallelGC:工作于新生代,复制算法
UseParallelOldGC:工作于老年代,标记整理算法
注意:开启其中一个会自动开启另一个

-XX:+UseAdaptiveSizePolicy

  • 功能:
    • 启用自适应大小调整(新生代)策略。该策略会根据运行时的统计信息动态调整新生代(Young Generation)的大小(Eden 区和 Survivor 区)、晋升老年代的阈值等内存分配参数。JVM 会根据当前垃圾回收的性能表现自动调整这些参数,以达到更好的性能优化效果。
    • 当启用此参数时,JVM 会根据应用程序的行为和垃圾回收统计数据,尝试找到最优的内存分配比例和晋升阈值,而无需手动指定诸如 -Xmn(新生代大小)或 -XX:SurvivorRatio 等参数。

-XX:GCTimeRatio=ratio

  • 功能:
    • 该参数用于设置吞吐量目标,它是一个控制垃圾回收时间占总运行时间比例的参数。它表示允许的最大垃圾回收时间与总运行时间的比例。
    • 具体计算方式为 1 / (1 + ratio)。例如,如果你设置 ratio = 19,那么最大总垃圾回收时间占总运行时间的比例为 1 / (1 + 19) = 5%
    • JVM 会尽量调整垃圾回收器的工作,以确保垃圾回收时间不超过总运行时间的这个比例,从而保证应用程序的吞吐量,提高程序执行效率。

-XX:MaxGCPauseMillis=ms

  • 功能:
    • 设定垃圾回收的最大暂停时间目标,单位是毫秒。JVM 会尽力将垃圾回收的暂停时间控制在这个目标值以内。默认200ms
    • 当设置此参数后,JVM 会调整堆内存大小、新生代和老年代的比例等,使每次垃圾回收的暂停时间尽可能不超过该值。
    • 然而,需要注意的是,为了达到这个目标,可能会导致更频繁的垃圾回收操作,或者减少堆内存的使用量,因此需要根据实际情况进行权衡,避免因过度追求低暂停时间而影响整体性能。

注意:-XX:MaxGCPauseMillis=ms和-XX:GCTimeRatio=ratio会有冲突。
当调整 -XX:MaxGCPauseMillis 以追求更短的暂停时间时,可能会影响 -XX:GCTimeRatio 所期望的吞吐量目标。

因为为了达到更短的暂停时间,可能会频繁进行垃圾回收,这会增加垃圾回收的总时间,导致垃圾回收时间占总运行时间的比例增加,从而可能无法达到 -XX:GCTimeRatio 设定的吞吐量目标。

反之,当调整 -XX:GCTimeRatio 以提高吞吐量时(一般会将堆内存增大),可能会导致单次垃圾回收的暂停时间变长(堆内存变大导致单次时间变长),从而可能超过 -XX:MaxGCPauseMillis 设定的暂停时间限制,影响对响应时间敏感的应用程序的性能。

-XX:ParallelGCThreads=n

  • 功能:
    • 用于设置并行垃圾回收器的线程数量为 n。
    • 在使用并行垃圾回收器(如 Parallel Scavenge 或 Parallel Old)时,该参数决定了在进行垃圾回收时同时运行的线程数量。
    • 通常,n 的值可以根据 CPU 核心数来确定。如果不设置此参数,JVM 会根据实际的 CPU 核心数自动设置一个合适的值。在多核心的环境下,增加并行垃圾回收线程的数量可以提高垃圾回收的效率,但过多的线程也可能会带来额外的线程切换开销,所以要根据实际硬件和应用程序的特点来合理设置此参数。

3.响应时间优先(ParNew 收集器/CMS 收集器)

ParNew 收集器其实就是 Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。
ParNew 收集器采用标记-复制算法
在这里插入图片描述
它是许多运行在 Server 模式下的虚拟机的首要选择,除了 Serial 收集器外,只有它能与 CMS 收集器配合工作

ParNew收集器是激活CMS后(使用-XX:+UseConcMarkSweepGC选项)的默认新生代收集器,也可以使用-XX:+/-UseParNewGC选项来强制指定或者禁用它。

自JDK 9开始还取消了ParNew加Serial Old以及Serial加CMS这两组收集器组合的支持,并直接取消了-XX:+UseParNewGC参数,这意味着ParNew和CMS从此只能互相搭配使用,再也没有其他收集器能够和它们配合了。

读者也可以理解为从此以后,ParNew合并入CMS,成为它专门处理新生代的组成部分。ParNew可以说是HotSpot虚拟机中第一款退出历史舞台的垃圾收集器。

CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用。

CMS(Concurrent Mark Sweep)收集器是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。

遗憾的是,CMS作为老年代的收集器,却无法与JDK 1.4.0中已经存在的新生代收集器Parallel Scavenge配合工作,所以在JDK 5中使用CMS来收集老年代的时候,新生代只能选择ParNew或者Serial收集器中的一个。

从名字中的Mark Sweep这两个词可以看出,CMS 收集器是一种 “标记-清除”算法实现的,它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤(其中初始标记、重新标记这两个步骤仍然需要“Stop The World”):

  • 初始标记: 短暂停顿,标记直接与 root 相连的对象(根对象);
  • 并发标记: 同时开启 GC 和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域,所以 GC 线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。(并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行;)
  • 重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短
  • 并发清除: 开启用户线程,同时 GC 线程开始对未标记的区域做清扫。(并发清除阶段清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。)

总结
初始标记时耗费时间特别少,只是标记根对象。之后进行并发标记,此时用户线程也在运行,所以可能会改变对象的引用,所以之后需要重新标记(也是stop-the-world),之后在并发清理。
在并发清理时用户线程产生的垃圾成为浮动垃圾,只能在下次垃圾回收时清理。
注意:该垃圾回收器对CPU的占用并不高,但是此时用户线程也会运行,又因为两者同时运行,所以在垃圾回收时,会对程序的吞吐量有影响。
在这里插入图片描述
CMS主要优点:并发收集、低停顿。但是它有下面三个明显的缺点:

  • 对 CPU 资源敏感;
  • 无法处理浮动垃圾;
  • 它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生。

CMS 垃圾回收器在 Java 9 中已经被标记为过时(deprecated),并在 Java 14 中被移除。

由于CMS收集器无法处理“浮动垃圾”(Floating Garbage),有可能出现“Con-current Mode Failure”失败进而导致另一次完全“Stop The World”的Full GC的产生。

在CMS的并发标记和并发清理阶段,用户线程是还在继续运行的,程序在运行自然就还会伴随有新的垃圾对象不断产生,但这一部分垃圾对象是出现在标记过程结束以后,CMS无法在当次收集中处理掉它们,只好留待下一次垃圾收集时再清理掉。

并行和并发概念补充:
并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行,可能会交替执行),用户程序在继续运行,而垃圾收集器运行在另一个 CPU 上。

相关参数

-XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld

UseConcMarkSweepGC:工作于老年代,基于标记清除的并发回收器,该垃圾回收器在运行时,其他用户线程也可以同时运行,但是在某些阶段还是需要stop-the-world。
UseParNewGC:工作于新生代,基于复制算法的垃圾回收器
SerialOld:UseConcMarkSweepGC回收器在有些情况下会出现并发失败的问题,此时会采取补救的措施,老年代会从并发回收器退化到单线程回收器。
并发失败的原因有:因为使用的基于标记清除的并发回收器,所以可能是因为内存碎片导致的,此时退化为单线程的垃圾回收器进行内存整理

-XX:ParallelGCThreads=n ~ -XX:ConcGCThreads=threads

ParallelGCThreads=n:并行线程数
ConcGCThreads=threads:并发GC线程数,一般设置为并行线程数的四分之一

-XX:CMSInitiatingOccupancyFraction=percent

在并发清理时用户线程产生的垃圾成为浮动垃圾,只能在下次垃圾回收时清理。如设置这个参数为占用老年代内存80%时会触发垃圾回收,预留一些空间存放浮动垃圾

-XX:+CMSScavengeBeforeRemark

在重新标记之前对新生代进行一次垃圾回收

4.G1(Garbage First收集器)

前言

在G1收集器出现之前的所有其他收集器,包括CMS在内,垃圾收集的目标范围要么是整个新生代(Minor GC),要么就是整个老年代(Major GC),再要么就是整个Java堆(Full GC)。

而G1跳出了这个樊笼,它可以面向堆内存任何部分来组成回收集(Collection Set,一般简称CSet)进行回收,衡量标准不再是它属于哪个分代,而是哪块内存中存放的垃圾数量最多,回收收益最大,这就是G1收集器的Mixed GC模式。G1开创的基于Region的堆内存布局是它能够实现这个目标的关键。

虽然G1也仍是遵循分代收集理论设计的,但其堆内存的布局与其他收集器有非常明显的差异:G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。

收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。

Region中还有一类特殊的Humongous区域,专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。
每个Region的大小可以通过参数-XX:G1HeapRegionSize设定,取值范围为1MB~32MB,且应为2的N次幂。而对于那些超过了整个Region容量的超级大对象,将会被存放在N个连续的Humongous Region之中,G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待。

介绍

G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征
被视为 JDK1.7 中 HotSpot 虚拟机的一个重要进化特征。它具备以下特点:

  • 并行与并发:G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行。
  • 分代收集:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。
  • 空间整合:与 CMS 的“标记-清除”算法不同,G1 从整体来看是基于“标记-整理”算法实现的收集器;从局部上来看是基于“标记-复制”算法实现的。
  • 可预测的停顿:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒。

G1 收集器的运作大致分为以下几个步骤:

  • 初始标记: 短暂停顿(Stop-The-World,STW),标记从 GC Roots 可直接引用的对象,即标记所有直接可达的活跃对象
  • 并发标记:与应用并发运行,标记所有可达对象。 这一阶段可能持续较长时间,取决于堆的大小和对象的数量。
  • 最终标记: 短暂停顿(STW),处理并发标记阶段结束后残留的少量未处理的引用变更。
  • 筛选回收:根据标记结果,选择回收价值高的区域,复制存活对象到新区域,回收旧区域内存。这一阶段包含一个或多个停顿(STW),具体取决于回收的复杂度。
    在这里插入图片描述
    G1 收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的 Region(这也就是它的名字 Garbage-First 的由来) 。这种使用 Region 划分内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。
    从 JDK9 开始,G1 垃圾收集器成为了默认的垃圾收集器。

G1 VS CMS

目前在小内存应用上CMS的表现大概率仍然要会优于G1,而在大内存应用上G1则大多能发挥其优势,这个优劣势的Java堆容量平衡点通常在6GB至8GB之间。当然,以上这些也仅是经验之谈,不同应用需要量体裁衣地实际测试才能得出最合适的结论,随着HotSpot的开发者对G1的不断优化,也会让对比结果继续向G1倾斜。

在这里插入图片描述

1.Young Collection

  • 会 STW

G1会把堆内存划分为一个个大小相等的区域,每个区域都可以独立作为伊甸园、幸存区、老年代。
在这里插入图片描述
以上白色区域表示空闲区域,E则代表伊甸园区域,新创建的对象放在其中。
当伊甸园逐渐被占满,就会触发一次新生代的垃圾回收

在这里插入图片描述
垃圾回收会通过复制算法将幸存对象放入幸存区S

在这里插入图片描述
当幸存区中对象也比较多时,会触发新生代垃圾回收,将一些对象晋升(老年代)O区域中,不满足晋升条件的会将对象复制到其他的幸存区中。

2.Young Collection + CM

  • 在 Young GC 时会进行 GC Root (根对象)的初始标记
  • 老年代占用堆空间比例达到阈值时,进行并发标记(不会 STW),由下面的 JVM 参数决定
    -XX:InitiatingHeapOccupancyPercent=percent (默认45%)
    在这里插入图片描述

3.Mixed Collection

会对 E、S、O 进行全面垃圾回收

  • 最终标记(Remark)会 STW
  • 拷贝存活(Evacuation)会 STW
    -XX:MaxGCPauseMillis=ms
    在这里插入图片描述
  • 伊甸园S中的幸存对象会被复制算法复制到幸存区中,幸存区S中不够年龄的对象也会被复制到其他幸存区中,符合晋升条件的对象会晋升到老年代O中。
  • 老年代垃圾回收时也采用的复制算法,将幸存对象复制到新的O中,老年代因为需要满足最大暂停时间MaxGCPauseMillis,所以会有选择的进行回收。
  • 因为有时候堆内存太大了,导致老年代的回收时间比较长。所以G1会从老年代中选择回收价值最高(垃圾最多的,可以释放更多的空间)的区域,复制的区域少了,时间自然就变短了。
  • 如果回收全部老年代也满足最大暂停时间,那么会回收所有老年代区域。

4.Full GC

当G1老年代内存不足时,老年代占用堆空间比例达到阈值(默认45%)时,进行并发标记。后续进行混合收集的阶段。

G1Full GC的时机:当垃圾回收的速度跟不上垃圾产生的速度时(并发回收失败)。此时会退化为串行回收阶段

5.Remark(重新标记阶段)

  • remark阶段就是为了防止出现被引用的被当成垃圾回收,没有被引用的没有被垃圾回收的情况。
  • 当对象的引用发生改变时,JVM会加入一个写屏障。如B对象被A对象引用,则会在引用上加上写屏障。
  • 当触发写屏障后,会将B对象加入一个队列中,并变为灰色表示没有处理完。等到并发标记结束后,进入重新标记阶段,重新标记阶段会SSW,暂停其他用户线程。将队列中的对象进行重新标记。队列的名称叫satb_mark_queue
    在这里插入图片描述
    以上图为并发标记阶段,对象的处理状态。
  • 黑色表示处理完成,并且被引用。所以表示垃圾回收后会被保留下来的对象。
  • 灰色表示处理当中的。
  • 白色表示尚未处理的。
  • 灰色、白色如果被引用,则最终会变成黑色。如果没有被引用则变为白色(并发标记后)被当成垃圾回收。

ZGC 收集器

与 CMS 中的 ParNew 和 G1 类似,ZGC 也采用标记-复制算法,不过 ZGC 对该算法做了重大改进。

ZGC 可以将暂停时间控制在几毫秒以内,且暂停时间不受堆内存大小的影响,出现 Stop The World 的情况会更少,但代价是牺牲了一些吞吐量。ZGC 最大支持 16TB 的堆内存。

ZGC 在 Java11 中引入,处于试验阶段。经过多个版本的迭代,不断的完善和修复问题,ZGC 在 Java15 已经可以正式使用了。
不过,默认的垃圾回收器依然是 G1。你可以通过下面的参数启用 ZGC:

java -XX:+UseZGC className

java -XX:+UseZGC className
在 Java21 中,引入了分代 ZGC,暂停时间可以缩短到 1 毫秒以内。
你可以通过下面的参数启用分代 ZGC:

java -XX:+UseZGC -XX:+ZGenerational className

相关文章:
JVM内存结构

  • JVM内存结构笔记01-运行时数据区域
  • JVM内存结构笔记02-堆
  • JVM内存结构笔记03-方法区
  • JVM内存结构笔记04-字符串常量池
  • JVM内存结构笔记05-直接内存
  • JVM内存结构笔记06-HotSpot虚拟机对象探秘
  • JVM中常量池和运行时常量池、字符串常量池三者之间的关系

JVM垃圾回收

  • JVM垃圾回收笔记01-垃圾回收算法
  • JVM垃圾回收笔记02-垃圾回收器

相关文章:

JVM垃圾回收笔记02-垃圾回收器

文章目录 前言1.串行(Serial 收集器/Serial Old 收集器)Serial 收集器Serial Old 收集器相关参数-XX:UseSerialGC 2.吞吐量优先(Parallel Scavenge 收集器/Parallel Old 收集器)Parallel Scavenge 收集器Parallel Old 收集器相关参数-XX:UseParallelGC ~ -XX:UseParallelOldGC-…...

Agent Team 多智能体系统解析

引言 在人工智能技术高速发展的今天,"多智能体协作系统"(Agent Team)正成为突破效率瓶颈的关键技术。与传统的单体AI不同,这种由多个专业化智能体组成的协同网络,通过分工协作和动态调整,展现出…...

LintCode第1712题 - 和相同的二元子数组

描述 在由若干 0 和 1 组成的数组 A 中,有多少个和为 S 的非空子数组 样例 1: 输入:A [1,0,1,0,1], S 2 输出:4 解释: 如下面黑体所示,有 4 个满足题目要求的子数组: [1,0,1] [1,0,1] [1,0,1,0] [0,1,…...

网络HTTPS协议

Https HTTPS(Hypertext Transfer Protocol Secure)是 HTTP 协议的加密版本,它使用 SSL/TLS 协议来加密客户端和服务器之间的通信。具体来说: • 加密通信:在用户请求访问一个 HTTPS 网站时,客户端&#x…...

0322-数据库、前后端

前端 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>Insert title here</title> <script srcjs/jquery-3.7.1.min.js></script> <script> //jquaryajax发起请求 //传参形式不同 post用data{}…...

六十天前端强化训练之第二十六天之Vue Router 动态路由参数大师级详解

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、知识讲解 1. Vue Router 核心概念 2. 动态路由参数原理 3. 参数传递方案对比 二、核心代码示例 1. 完整路由配置 2. 参数接收组件 3. 导航操作示例 三、实现效果示…...

L2TP实验

一、拓朴图 二、实验配置 1.基础配置 1.1接口IP及服务配置 [PPPoE Client]interface GigabitEthernet 0/0/0 [PPPoE Client-GigabitEthernet0/0/0]service-manage all permit [NAS]interface GigabitEthernet 0/0/0 [NAS-GigabitEthernet0/0/0]ip add 192.168.0.2 24 [NAS-Gi…...

uni-app——数据缓存API

数据缓存API 在 uni-app 开发中&#xff0c;数据缓存 API 起着重要作用&#xff0c;它能够将需要的数据保存到本地&#xff0c;同时也提供了获取本地缓存数据、移除缓存数据以及清理缓存数据的功能。在实际项目里&#xff0c;数据缓存 API 常被用于存储会员登录状态信息、购物…...

不做颠覆者,甘为连接器,在技术叠层中培育智能新物种

--- 一、技术融合的必然&#xff1a;从“非此即彼”到“兼容共生” 当大模型的热浪撞上传统IT的礁石&#xff0c;企业智能化的真相浮出水面&#xff1a; 新旧技术的“量子纠缠”&#xff1a;MySQL与向量数据库共享数据总线&#xff0c;规则引擎与大模型共处决策链路 需求进…...

尝试在软考65天前开始成为软件设计师-计算机网络

OSI/RM 七层模型 层次名功能主要协议7应用层实现具体应用功能 FTP(文件传输)、HTTP、Telnet、 POP3(邮件)SMTP(邮件) ------- DHCP、TFTP(小文件)、 SNMP、 DNS(域名) 6表示层数据格式,加密,压缩.....5会话层建立,管理&终止对话4传输层端到端连接TCP,UDP3网络层分组传输&a…...

JDBC 连接字连接 KingbaseES支持主从负载均衡参数说明。

JDBC 连接字符串是用于连接 KingbaseES&#xff08;人大金仓数据库&#xff09;的&#xff0c;支持主从负载均衡。让我们逐一解析各个参数的作用&#xff0c;并探讨如何调整到最优。 参数解析 jdbc:kingbase8://10.10.14.19:54321/xxx_onlinejdbc:kingbase8://&#xff1a;指定…...

OpenCV旋转估计(4)生成一个字符串表示的匹配图函数 matchesGraphAsString()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 matchesGraphAsString 函数是OpenCV库中的一部分&#xff0c;位于 cv::detail 命名空间下。这个函数的主要作用是生成一个字符串表示的匹配图&am…...

扣子平台知识库不能上传成功

扣子平台知识库不能上传成功 目录 扣子平台知识库不能上传成功查看模板复制头部到自己的excel中json数据转为excel或者csv&#xff08;一定使用excel&#xff0c;csv总是报错&#xff09; 查看模板复制头部到自己的excel中 json数据转为excel或者csv&#xff08;一定使用excel&…...

CIFAR10 数据集自定义处理方法

CIFAR10 数据集自定义处理方法 可以自定义训练集和测试集中不同类别的样本的数量。可用于模拟类别不平衡问题&#xff0c;存在混淆数据问题。 import torch import torchvision.datasets as dsets import torchvision.transforms as transforms from torch.utils.data import…...

当发现提示少文件,少目录时时,external.css的内容

[ERROR ]17:30:44| Loger: 处理群消息时发生错误&#xff1a;[Errno 2] No such file or directory: \\venv\\lib\\site-packages\\ncatbot\\utils\\template/external.css venv\\lib\\site-packages\\ncatbot\\utils\\template/external.css ["https://stackpath.boots…...

OpenHarmony 开源鸿蒙北向开发——linux使用make交叉编译第三方库

这几天搞鸿蒙&#xff0c;需要编译一些第三方库到鸿蒙系统使用。 头疼死了&#xff0c;搞了一个多星期总算搞定了。 开贴记坑。 一、SDK下载 1.下载 在linux下使用命令 wget https://cidownload.openharmony.cn/version/Master_Version/OpenHarmony_5.1.0.54/20250313_02…...

【计算机网络】网络简介

文章目录 1. 局域网与广域网1.1 局域网1.2 广域网 2. 路由器和交换机3. 五元组3.1 IP和端口3.2 协议3.3 协议分层 4. OSI七层网络协议5. TCP/IP五层模型5.1 TCP/IP模型介绍5.2 网络设备所在分层 6. 封装与分用6.1 数据包的称谓6.2 封装6.3 分用 1. 局域网与广域网 1.1 局域网 …...

k8s--集群内的pod调用集群外的服务

关于如何让同一个局域网内的Kubernetes服务的Pod访问同一局域网中的电脑上的服务。 可能的解决方案包括使用ClusterIP、NodePort、Headless Service、HostNetwork、ExternalIPs&#xff0c;或者直接使用Pod网络。每种方法都有不同的适用场景&#xff0c;需要逐一分析。 例如&…...

高性能边缘计算网关-高算力web组态PLC网关

高性能EG8200Pro边缘计算算力网关-超强处理能力 样机申请测试&#xff1a;免费测试超30天&#xff08;https://www.iotrouter.com/prototype/&#xff09; 产品主要特点和特色功能 设备概览与连接能力 设备型号&#xff1a;EG8200P。主要特点&#xff1a; 支持多种工业协议&am…...

计算机视觉总结

以下是针对上述问题的详细解答,并结合代码示例进行说明: 1. 改进YOLOv5人脸检测模块,复杂光照场景准确率从98.2%提升至99.5% 优化具体过程: 光照补偿:在数据预处理阶段,采用自适应光照补偿算法,对图像进行实时增强,以减少光照变化对人脸检测的影响。数据增强:在训练…...

【Golang】defer与recover的组合使用

在Go语言中&#xff0c;defer和recover是两个关键特性&#xff0c;通常结合使用以处理资源管理和异常恢复。以下是它们的核心应用场景及使用示例&#xff1a; 1. defer 的应用场景 defer用于延迟执行函数调用&#xff0c;确保在函数退出前执行特定操作。主要用途包括&#xff…...

Beyond Compare 4注册激活方法

Beyond Compare 4 注册码 --- BEGIN LICENSE KEY --- H1bJTd2SauPv5Garuaq0Ig43uqq5NJOEw94wxdZTpU-pFB9GmyPk677gJ vC1Ro6sbAvKR4pVwtxdCfuoZDb6hJ5bVQKqlfihJfSYZt-xVrVU270Ja hFbqTmYskatMTgPyjvv99CF2Te8ecYs2SPxyZAF0YwOCNOWmsyqN5y9t q2Kw2pjoiDs5gIH-uw5U49JzOB6otS7kT…...

[C++游戏开发基础]:构造函数浅析,8000+字长文

构造函数 构造函数是一种特殊的成员函数,在创建非聚合类类型对象后会自动被调用。当定义一个非聚合类类型对象时,编译器会检查是否能找到一个可以访问的构造函数,该构造函数与调用者提供的初始化值(如果有的情况下)相匹配。 如果找到一个可访问的匹配构造函数&#xff0c;将为…...

【Go】切片

知识点关键概念切片声明var slice []int初始化切片slice : []int{1,2,3}make() 创建切片make([]int, len, cap)获取长度和容量len(slice), cap(slice)追加元素slice append(slice, value)切片截取slice[start:end]&#xff08;返回子切片&#xff09;拷贝切片copy(dest, src)&…...

MySQL 设置允许远程连接完整指南:安全与效率并重

一、为什么需要远程连接MySQL&#xff1f; 在分布式系统架构中&#xff0c;应用程序与数据库往往部署在不同服务器。例如&#xff1a; Web服务器&#xff08;如NginxPHP&#xff09;需要连接独立的MySQL数据库数据分析师通过BI工具直连生产库多服务器集群间的数据同步 但直接…...

Cursor IDE 入门指南

什么是 Cursor? Cursor 是一款集成了 AI 功能的现代代码编辑器&#xff0c;基于 VSCode 开发&#xff0c;专为提高开发效率而设计。它内置强大的 AI 助手功能&#xff0c;能够理解代码、生成代码、解决问题&#xff0c;帮助开发者更快、更智能地完成编程任务。 基础功能 1.…...

32.[前端开发-JavaScript基础]Day09-元素操作-window滚动-事件处理-事件委托

JavasScript事件处理 1 认识事件处理 认识事件(Event) 常见的事件列表 认识事件流 2 事件冒泡捕获 事件冒泡和事件捕获 事件捕获和冒泡的过程 3 事件对象event 事件对象 event常见的属性和方法 事件处理中的this 4 EventTarget使用 EventTarget类 5 事件委托模式 事件委托&am…...

【工具变量】中国各地级市是否属于“信息惠民国家试点城市”匹配数据(2010-2024年)

数据来源&#xff1a;国家等12部门联合发布的《关于加快实施信息惠民工程有关工作的通知》 数据说明&#xff1a;内含原始文件和匹配结果&#xff0c;当试点城市在2014年及以后&#xff0c;赋值为1&#xff1b;试点城市在2014年之前或该城市从未实施信息惠民试点工程&#x…...

windows安装配置FFmpeg教程

1.先访问官网&#xff1a;https://www.gyan.dev/ffmpeg/builds/ 2.选择安装包Windows builds from gyan.dev 3. 下滑找到release bulids部分&#xff0c;选择ffmpeg-7.0.2-essentials_build.zip 4. 然后解压将bin目录添加path系统变量&#xff1a;\ffmpeg-7.0.2-essentials_bui…...

Wispr Flow,AI语言转文字工具

Wispr Flow是什么 Wispr Flow 是AI语音转文本工具&#xff0c;基于先进的AI技术&#xff0c;帮助用户在任何应用程序中实现快速语音转文字。 Wispr Flow支持100多种语言&#xff0c;具备自动编辑、上下文感知和低音量识别等功能&#xff0c;大幅提升写作和沟通效率。Wispr Fl…...

风暴潮、潮汐潮流模拟:ROMS模型如何精准预测海洋现象?

海洋数值模拟的崛起与 ROMS 的关键角色 &#x1f30a;在海洋科学的浪潮中&#xff0c;海洋数值模拟正以迅猛之势崛起&#xff0c;成为科研与实际应用领域不可或缺的利器。ROMS&#xff08;Regional Ocean Modeling System&#xff09;作为其中的佼佼者&#xff0c;凭借其高效、…...

【Rust】集合的使用——Rust语言基础16

文章目录 1. 前言2. Vector2.1. 构建一个 vector2.2. 获取 vector 中的元素2.3. 遍历 vector2.4. 使用枚举来储存多种类型 3. String3.1. 新建字符串3.2. 更新字符串3.3. 字符串的内部结构3.3.1. 字符串如何访问内部元素&#xff1f;3.3.2. 字节、标量值和字形簇 3.4. 字符串 s…...

Kafka集成Debezium监听postgresql变更

下载postgres的插件&#xff1a;https://debezium.io/documentation/reference/2.7/install.html 2.7版本支持postgresql12数据库。 debezium-connector-postgres-2.7.4.Final-plugin.tar.gz 上传插件并解压 mkdir /usr/local/kafka/kafka_2.12-2.2.1/connector cd /usr/local…...

自动学习和优化过程,实现更加精准的预测和决策的智慧交通开源了

智慧交通视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。通过高效的实时视…...

第2.2节 Android Jacoco插件覆盖率采集

JaCoCo&#xff08;Java Code Coverage&#xff09;是一款开源的代码覆盖率分析工具&#xff0c;适用于Java和Android项目。它通过插桩技术统计测试过程中代码的执行情况&#xff0c;生成可视化报告&#xff0c;帮助开发者评估测试用例的有效性。在github上开源的项目&#xff…...

从零开始:使用 Cython + JNI 在 Android 上运行 Python 算法

1. 引言 在 Android 设备上运行 Python 代码通常面临性能、兼容性和封装等挑战。尤其是当你希望在 Android 应用中使用 Python 编写的计算密集型算法时&#xff0c;直接运行 Python 代码可能导致较高的 CPU 占用和较差的性能。为了解决这个问题&#xff0c;我们可以使用 Cytho…...

开源软件许可证冲突的原因和解决方法

1、什么是开源许可证以及许可证冲突产生的问题 开源软件许可证是一种法律文件&#xff0c;它规定了软件用户、分发者和修改者使用、复制、修改和分发开源软件的权利和义务。开源许可证是由软件的版权所有者&#xff08;通常是开发者或开发团队&#xff09;发布的&#xff0c;它…...

stratis,容器podman

一、stratis 1.stratis可以实现动态的在线扩容&#xff0c;lvm虽然也可以实现在线扩容&#xff0c;但是是需要人为的手动扩容。 2.stratis不需要手动格式化&#xff0c;自动会创建文件系统&#xff08;默认是xfs&#xff09; 1. 安装stratis软件包 yum list | grep stratis…...

解决用three.js展示n个叠加的stl模型文件错位的问题

加载stl时可以明显看到下面有一部分模型是错位的。 将stl文件格式转化为glb 使用免费将 STL 转换为 GLB - ImageToStl 模型就没有错位了 代码如下 <template><div ref"threeContainer" class"three-container"></div></template&…...

从零开始实现 C++ TinyWebServer 数据库连接池 SqlConnectPool详解

文章目录 数据库连接池是什么&#xff1f;Web Server 中为什么需要数据库连接池&#xff1f;SqlConnectPool 成员变量实现 Init() 函数实现 ClosePool() 函数SqlConnectRAII 类SqlConnectPool 代码SqlConnectPool 测试 从零开始实现 C TinyWebServer 项目总览 项目源码 数据库连…...

利用ffmpeg库实现音频AAC编解码

AAC‌&#xff08;Advanced Audio Coding&#xff09;是一种音频编码技术&#xff0c;出现于1997年&#xff0c;基于MPEG-2的音频编码技术。AAC具有高效的数据压缩能力和较高的音质&#xff0c;适用于各种音频应用场景。例如&#xff0c;在智能设备中&#xff0c;AAC技术被广泛…...

Vue + CSS实现渐变栅格进度条

进度条作为可视化大屏系统中展示数据状态的关键元素&#xff0c;其视觉效果直接影响用户的使用体验&#xff0c;而传统的进度条往往呈现出固定的样式&#xff0c;缺乏视觉吸引力。在这种场景下&#xff0c;一种基于Vue和CSS实现渐变栅格进度条的方法应运而生&#xff0c;该方法…...

算法模型从入门到起飞系列——背包问题(探索最大价值的掘金之旅)

文章目录 前言一、背包问题溯源&#xff08;动态规划&#xff09;1.1 动态规划的概念1.2 动态规划的基本步骤1.3 动态规划的实际应用 二、背包问题2.1 背包问题衍生2.2 0-1背包2.2.1 0-1背包描述2.2.2 0-1背包图解2.2.3 0-1背包代码刨析 2.3 完全背包2.3.1 完全背包描述2.3.2 完…...

蓝桥杯—迷宫(bfs)

一.题目 分析:最短路径问题&#xff0c;给定一个迷宫&#xff0c;从左上角走到右下角&#xff0c;要求路径最短&#xff0c;并且要求字典序最小&#xff0c;也就是按照D&#xff0c;L&#xff0c;R&#xff0c;U&#xff0c;的搜索顺序去搜索&#xff0c;否则路径不是唯一的&am…...

【Android】安卓 Java下载ZIP文件并解压(笔记)

写在前面的话 在这篇文章中&#xff0c;我们将详细讲解如何在 Android 中通过 Java 下载 ZIP 文件并解压&#xff0c;同时处理下载进度、错误处理以及优化方案。 以下正文 1.权限配置 在 AndroidManifest.xml 中&#xff0c;我们需要添加相应的权限来确保应用能够访问网络和设…...

清晰易懂的 PHP 安装与配置教程

初学者也能看懂的 PHP 安装与配置教程 本教程将手把手教你如何在 Windows 系统上安装 PHP&#xff0c;并配置 Composer&#xff08;PHP 的依赖管理工具&#xff09;的缓存位置&#xff0c;即使你是零基础小白&#xff0c;也能轻松完成&#xff01; 一、准备工作 操作系统&…...

Ceph集群2025(Squid版)快速对接K8S cephFS文件存储

ceph的块存储太简单了。所以不做演示 查看集群 创建一个 CephFS 文件系统 # ceph fs volume create cephfs01 需要创建一个子卷# ceph fs subvolume create cephfs01 my-subvol -----------------#以下全部自动创建好 # ceph fs ls name: cephfs01, metadata pool: c…...

Linux进程控制(四)之进程程序替换

文章目录 进程程序替换单进程版程序替换替换原理多进程版程序替换替换函数函数解释小知识 命名理解 进程程序替换 如果要让子进程执行与父进程完全不同的代码&#xff0c;就要进行进程程序替换。 单进程版程序替换 执行一个可执行文件 makefile mycommand:mycommand.cgcc -…...

python-selenium 爬虫 由易到难

本质 python第三方库 selenium 空值 浏览器驱动 浏览器驱动控制浏览器 推荐 edge 浏览器驱动&#xff08;不容易遇到版本或者兼容性的问题&#xff09; 驱动下载网址&#xff1a;链接: link 1、实战1 &#xff08;1&#xff09;安装 selenium 库 pip install selenium&#…...

希尔排序

希尔排序是一种改进的插入排序算法&#xff0c;它通过将原始数据分成多个子序列来改善插入排序的性能&#xff0c;每个子序列的元素间隔为 d&#xff08;增量&#xff09;。随着算法的进行&#xff0c;d 逐渐减小&#xff0c;最终减为 1&#xff0c;此时整个序列就被排序好了。…...