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

news2025/3/25 20:21:34

文章目录

  • 前言
  • 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-垃圾回收器

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

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

相关文章

Linux上位机开发实战(编写API库)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 我们自己编写linux上位机软件的时候,尽量都是通过框架库的形式来开发。这就是所谓的低耦合,高内聚。相似的功能、模块和算法…

器件功耗模型原理

器件功耗模型原理 谷歌提供了一套通用的器件耗电模型和配置方案,先对器件进行耗电因子拆解,建立器件功耗模型,得到一个器件耗电的计算公式。通过运行时统计器件的使用数据,代入功耗模型,就可以计算出器件的功耗。例如…

拥抱成长型思维:解锁持续进步的人生密码

我强烈推荐4本可以改变命运的经典著作: 《寿康宝鉴》在线阅读白话文《欲海回狂》在线阅读白话文《阴律无情》在线阅读白话文《了凡四训》在线阅读白话文 一、什么是成长型思维? 成长型思维(Growth Mindset)由斯坦福大学心理学家卡…

Ubuntu上查看GPU使用情况并释放内存

先用nvidia-smi查看GPU当前使用情况 再用fuser 命令查找对应显卡上占用 GPU 的进程 最后查到了用kill -9强制杀掉进程(PID)即可

解决思科交换机无法访问局域网外设备

问题背景 有时,我们需要远程连接来管理一台思科交换机,例如使用SSH协议。然而交换机运作在链路层,这就需要交换机有一个网络层地址,来接纳基于IP协议的远程访问请求。于是,我们依靠设置一个带有IP地址的交换机虚拟接口…

什么是张量计算

以下是对张量计算的详细介绍,结合数学、物理学及计算机科学等多领域视角: 一、张量的基本定义与性质 1. 张量的数学定义 张量是向量空间及其对偶空间的笛卡尔积上的多重线性映射,可视为多维数组或几何对象。其核心特征在于: 坐…

【1】Java 零基础入门学习(小白专用)

【1】Java 零基础入门学习 📚博客主页:代码探秘者 ✨专栏:《JavaSe从入门到精通》 其他更新ing… ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏作者水…

[c语言日寄]枚举类型

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…

【氧化镓】​​​​掺杂在β-Ga2O3材料中引入的深能级缺陷

1. 引言 1.1 β-Ga2O3材料的特性与应用前景 β-Ga2O3作为一种新型的宽禁带半导体材料,具有约4.6-4.8 eV的宽带隙、高击穿场强(约8 MV/cm)和优异的热稳定性,适用于高功率和射频电子器件。其独特的物理特性使其在高电压、高频率以及高功率应用场景中具有巨大的潜力。例如,…

仅靠prompt,Agent难以自救

Alexander的观点很明确:未来 AI 智能体的发展方向还得是模型本身,而不是工作流(Work Flow)。还拿目前很火的 Manus 作为案例:他认为像 Manus 这样基于「预先编排好的提示词与工具路径」构成的工作流智能体,…

Playwright + MCP:用AI对话重新定义浏览器自动化,效率提升300%!

一、引言:自动化测试的“瓶颈”与MCP的革新 传统自动化测试依赖开发者手动编写脚本,不仅耗时且容易因页面动态变化失效。例如,一个简单的登录流程可能需要开发者手动定位元素、处理等待逻辑,甚至反复调试超时问题。而MCP&#xf…

计算机操作系统(五) 前趋图和程序执行与进程的描述(附带图谱表格更好对比理解))

计算机操作系统(五) 前趋图和程序执行与进程的描述 前言一、前趋图和程序执行1.1前趋图1.2程序的顺序执行1.3程序的并发执行 二、进程的描述2.1进程的定义与特征2.2进程的基本状态与转换2.3挂起的操作系统和进程的转换2.4进程管理中的数据结构 总结&…

C/C++静态库的理解和制作

1.什么是库 库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。 本质上来说库是⼀种可执行代码的二进制形式,可以被操作系统…

【redis】主从复制:单点问题、配置详解、特点详解

文章目录 单点问题什么是主从复制主从模式能解决的问题并发量有限可用性问题 配置建立复制通过配置文件来指定端口配置主从查看集群结构 断开复制 特点安全性只读传输延迟 单点问题 分布式系统中,涉及到一个非常关键的问题:单点问题 某个服务器程序&…

android......

事件源,就是视图对象,先注册一个监听器,等待用户触发了屏幕,一旦触发会立即产生一个事件源,事件源会生成一个用户点击的触发事件,此刻监听器会立马监听到 ,然后监听器调用回调方法 UI理解 全称用…

常见中间件漏洞(tomcat)

CVE-2017-12615 当在Tomcat的conf(配置目录下)/web.xml配置文件中添加readonly设置为false时,将导致该漏洞产生,(需要允许put请求) , 攻击者可以利用PUT方法通过精心构造的数据包向存在漏洞的服务器里面上传…

计算机网络高频(二)TCP/IP基础

计算机网络高频(二)TCP/IP基础 1.什么是TCP/IP⭐⭐ TCP/IP是一种网络通信协议,它是互联网中最常用的协议之一。TCP/IP有两个基本的协议:TCP(传输控制协议)和IP(互联网协议)。 TCP(Transmission Control Protocol,传输控制协议)是一种可靠的、面向连接的协议。它负…

国际护士节知识竞赛主持稿串词

在这充满火热激情的季节,我们又迎来了5.12国际护士节。让我们首先向辛勤奋战在护理工作一线的全县广大护士姐妹们道一声: (男)让我们再一次以热烈的掌声欢迎他们:预祝各参赛代表队在护理知识竞赛中赛出风格,赛出水平,取得满意的成绩。 (女)…

Elasticsearch:可配置的推理 API 端点分块设置

作者:来自 Elastic Daniel Rubinstein Elasticsearch 开放推理 API 现已支持可配置的分块,以便在文档摄取时处理语义文本字段。 Elasticsearch 推理 API 允许用户利用各种提供商的机器学习模型执行推理操作。其中一个常见用例是在索引中支持用于语义搜索…

数据结构之链表(双链表)

目录 一、双向带头循环链表 概念 二、哨兵位的头节点 优点: 头节点的初始化 三、带头双向链表的实现 1.双链表的销毁 2.双链表的打印 3.双链表的尾插和头插 尾插: 头插: 4.双链表的尾删和头删 尾删: 头删: …