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

JVM——垃圾回收

垃圾回收

在Java虚拟机(JVM)的自动内存管理中,垃圾回收(Garbage Collection, GC)是其核心组件之一。它负责回收堆内存中不再使用的对象所占用的内存空间,以供新对象的分配使用。下面我们将深入探讨JVM中的垃圾回收机制。

垃圾回收的基本概念

垃圾回收的主要目标是自动回收不再使用的内存,从而避免内存泄漏和手动内存管理带来的错误。在JVM中,垃圾回收器会定期扫描堆内存,识别并回收那些不再被程序使用的对象。这个过程中涉及到的关键问题是:如何判断一个对象是否已经“死亡”,即是否可以被回收。

引用计数法与可达性分析

(一)引用计数法

引用计数法是一种古老的垃圾回收算法,其基本思想是为每个对象维护一个计数器,用于记录指向该对象的引用数量。每当有一个新的引用指向该对象时,计数器加1;当引用不再存在时,计数器减1。当计数器的值为0时,表示该对象不再被引用,可以被回收。

  • 优点 :实现简单,能够及时回收不再被引用的对象。

  • 缺点 :需要额外的空间来存储计数器,并且在引用关系频繁变化时,计数器的更新操作会带来一定的性能开销。最严重的缺陷是无法处理循环引用问题,即两个或多个对象相互引用,导致它们的计数器始终大于0,即使它们实际上已经不再被程序使用,也无法被回收。

(二)可达性分析

可达性分析是现代JVM中主流的垃圾回收算法。它的核心思想是从一组称为GC Roots的对象开始,这些对象是垃圾回收的起点。然后,算法会从GC Roots出发,递归地遍历所有可以直接或间接引用的对象,标记这些存活的对象。最终,未被标记的对象即为可以回收的垃圾对象。

  • GC Roots的组成 :在JVM中,GC Roots通常包括以下几类对象:

    • Java方法栈中的局部变量 :这些变量可能引用堆中的对象,作为GC Roots的起点。

    • 已加载类的静态变量 :类的静态变量在类加载时会被分配内存,它们可能引用堆中的对象。

    • JNI handles :Java Native Interface(JNI)允许Java代码与本地代码(如C/C++)交互,JNI handles是本地代码中引用Java对象的句柄。

    • 已启动且未停止的Java线程 :线程本身可能引用堆中的对象,如线程的堆栈中的局部变量等。

  • 优点 :能够解决引用计数法无法处理的循环引用问题,准确地识别出不再使用的对象。

  • 缺点 :需要暂停应用程序的执行,进行全堆扫描以确定GC Roots,并递归遍历引用对象,这会导致Stop-the-World(STW)现象,影响应用程序的性能。

Stop-the-World(STW)现象

在垃圾回收过程中,传统的垃圾回收算法需要确保在标记存活对象的过程中,堆栈的状态不会发生改变,否则可能导致标记结果不准确,从而引发误报或漏报问题。为了解决这个问题,JVM采用了Stop-the-World机制,即在垃圾回收时暂停所有非垃圾回收线程的工作,直到垃圾回收完成。这期间,应用程序的执行被暂停,等待垃圾回收线程完成其任务,这就是所谓的STW现象。

STW现象会导致应用程序的暂停,影响用户体验和系统的吞吐量。尤其是在处理大数据量或高并发场景时,长时间的STW暂停可能是不可接受的。因此,现代垃圾回收器致力于减少STW暂停的时间,提高垃圾回收的效率。

安全点机制

为了实现Stop-the-World,JVM引入了安全点(safepoint)机制。安全点是一个程序执行的状态点,在这个状态下,堆栈不会发生变化,垃圾回收器可以“安全”地执行垃圾回收操作。当JVM需要触发垃圾回收时,它会等待所有线程都到达安全点后,暂停这些线程,然后进行垃圾回收。

  • 安全点的设置 :在JVM中,安全点的设置需要考虑不同执行状态的线程。例如:

    • 解释执行字节码 :字节码与字节码之间都可以作为安全点。当有安全点请求时,JVM会在执行每条字节码后进行安全点检测。

    • 执行即时编译器生成的机器码 :由于这些代码直接运行在底层硬件上,不受JVM直接控制,因此即时编译器需要在生成的机器码中插入安全点检测代码。通常在方法出口、非计数循环的循环回边等位置插入安全点检测。

    • JNI本地代码执行 :当Java程序通过JNI调用本地代码时,如果这段代码不访问Java对象、不调用Java方法或不返回Java方法,那么它可以被视为一个安全点。JVM只需在JNI API的入口处进行安全点检测,即可在必要时挂起当前线程。

  • 安全点检测的开销 :虽然安全点检测本身会带来一定的性能开销,但JVM通过优化设计,将其简化为一个内存访问操作。在需要进行安全点检测时,JVM会将访问的内存所在的页设置为不可读,并定义一个segfault处理器来截获访问该不可读内存的线程,将其挂起。

不同即时编译器插入安全点检测的位置可能不同。例如,Graal编译器除了在方法出口和非计数循环回边处插入安全点检测外,还会在计数循环的循环回边处插入检测点,以确保更频繁地进入安全点,减少垃圾回收的暂停时间。

垃圾回收的三种方式

在完成存活对象的标记后,垃圾回收器需要对死亡对象的内存进行回收。现代垃圾回收器通常采用以下三种基本回收方式中的一种或多种组合:

(一)清除(Sweep)

  • 原理 :将死亡对象所占据的内存标记为空闲内存,并记录在一个空闲列表中。当需要分配新对象时,内存管理模块从空闲列表中查找足够大小的空闲内存块进行分配。

  • 优点 :实现简单,回收速度快。

  • 缺点 :容易造成内存碎片。随着时间的推移,堆内存中的空闲空间可能变得零散,无法满足大对象的分配需求,导致内存分配失败。

(二)压缩(Compact)

  • 原理 :将存活的对象移动到内存区域的起始位置,消除内存碎片,形成一段连续的空闲内存空间。

  • 优点 :解决了内存碎片问题,提高了内存的利用率。

  • 缺点 :需要移动对象并更新引用,这会增加垃圾回收的暂停时间,影响应用程序的性能。

(三)复制(Copy)

  • 原理 :将内存区域分为两个相等的部分,称为from空间和to空间。新对象在from空间中分配内存。当from空间填满时,触发垃圾回收,将存活对象复制到to空间中,然后交换from和to空间的角色。

  • 优点 :能够有效解决内存碎片问题,且垃圾回收过程简单高效。

  • 缺点 :内存利用率较低,因为只有一半的内存空间用于对象分配。

现代垃圾回收器通常会结合这些回收方式的优点,根据不同的场景和需求,灵活地选择和组合回收策略。例如,在新生代垃圾回收中,通常采用复制算法,因为它能够快速回收大量短生命周期的对象;而在老年代垃圾回收中,可能采用标记 - 清除或标记 - 压缩算法,以减少暂停时间并提高内存利用率。

Java虚拟机的堆划分

JVM的堆内存是垃圾回收的主要区域,其划分策略对垃圾回收的效率有着重要影响。JVM将堆分为新生代和老年代,这种分代回收思想基于一个重要的观察:大多数Java对象的生命周期很短,只有少数对象会存活较长时间。

(一)新生代

新生代用于存储新创建的对象。新生代的内存划分为一个Eden区和两个大小相同的Survivor区(通常称为S0和S1)。

  • 对象分配 :大多数新创建的对象首先在Eden区分配内存。当Eden区填满时,会触发Minor GC。

  • Minor GC :在Minor GC过程中,垃圾回收器会将Eden区和当前使用的Survivor区(假设为S0)中存活的对象复制到另一个Survivor区(S1),然后交换S0和S1的角色。如果一个对象在多次Minor GC中都存活下来,并且其在Survivor区中的复制次数达到一定的阈值(默认为15次),该对象将被晋升到老年代。

(二)老年代

老年代用于存储从新生代晋升过来的长期存活对象,以及直接在老年代分配的大对象(通过-XX:PretenureSizeThreshold参数设置大对象的大小阈值)。

  • 对象分配 :当对象的大小超过-XX:PretenureSizeThreshold参数设置的值时,或者对象无法在新生代中分配时(如新生代内存不足),对象会直接分配在老年代。

  • Major GC :针对老年代的垃圾回收称为Major GC。由于老年代的对象通常具有较长的生命周期,Major GC发生的频率较低,但其暂停时间往往较长。现代垃圾回收器致力于通过并发收集等技术减少Major GC的暂停时间。

(三)TLAB(Thread Local Allocation Buffer)

为了提高内存分配的效率,减少线程间的内存分配竞争,JVM引入了TLAB技术。

  • 原理 :每个线程可以向JVM申请一段连续的内存作为TLAB。线程在TLAB中为新对象分配内存时,通过简单的指针加法(pointer bumping)操作即可完成,无需进行同步操作,大大提高了内存分配的速度。

  • TLAB的管理 :线程维护两个指针,一个指向TLAB中空闲内存的起始位置,另一个指向TLAB的末尾。当为新对象分配内存时,线程会检查起始指针加上所需内存大小是否小于等于末尾指针。如果是,则分配成功;否则,线程需要申请一个新的TLAB。

  • 优点 :显著提高了多线程环境下内存分配的效率,减少了线程间的竞争和同步开销。

  • 缺点 :如果TLAB的大小设置不合理,可能会导致内存浪费。如果TLAB过大,可能会造成内存利用率低下;如果TLAB过小,则会增加申请新TLAB的频率,增加开销。

卡表

为了避免在Minor GC时扫描整个老年代以寻找对新生代对象的引用,JVM引入了卡表(Card Table)技术。

  • 原理 :将整个堆内存划分为大小为512字节的卡。卡表是一个数组,每个元素对应一张卡的标识位。当老年代中的对象引用新生代中的对象时,对应的卡会被标记为“脏卡”。

  • 写屏障 :为了维护卡表的准确性,JVM在编译器生成的机器码中插入写屏障(write barrier)代码。写屏障会在更新引用型实例变量时执行,通过计算引用地址所在的卡,并将该卡标记为脏卡。写屏障的实现需要尽可能简洁高效,以减少对程序性能的影响。

  • Minor GC中的卡表应用 :在Minor GC过程中,垃圾回收器只需要扫描卡表中被标记为脏卡的区域,检查这些区域中的对象是否引用了新生代中的存活对象。这些引用会被加入到GC Roots中,确保新生代中的存活对象不会被错误地回收。扫描完成后,卡表中的脏卡标识位会被清零。

卡表技术有效地减少了Minor GC时需要扫描的老年代内存范围,提高了垃圾回收的效率。然而,写屏障的使用也会带来一定的性能开销,尤其是在高并发环境下,可能会引发虚共享(false sharing)问题。为了解决这一问题,HotSpot引入了-XX:+UseCondCardMark参数,通过优化写屏障逻辑,减少不必要的卡表标记操作。

垃圾回收器详解

在JVM中,有多种垃圾回收器可供选择。不同的垃圾回收器适用于不同的应用场景和性能需求。

(一)新生代垃圾回收器

  • Serial :是一个单线程的垃圾回收器,采用标记 - 复制算法。其特点是简单高效,适用于单核处理器或CPU资源受限的环境。由于其单线程特性,在多核环境下可能无法充分利用CPU资源。

  • Parallel Scavenge :是Serial的多线程版本,注重吞吐量。吞吐量是指应用程序运行时间与总时间(包括垃圾回收时间)的比值。Parallel Scavenge适用于对吞吐量要求较高的场景,如批处理任务等。

  • Parallel New :同样是Serial的多线程版本,但更注重垃圾回收的暂停时间。适用于对暂停时间敏感的应用,如用户交互型应用等。

(二)老年代垃圾回收器

  • Serial Old :是Serial的同伴,用于老年代的垃圾回收。采用标记 - 压缩算法,单线程工作。适用于单核处理器或小规模应用的老年代垃圾回收。

  • Parallel Old :是Serial Old的多线程版本,适用于多核环境下老年代的垃圾回收。通过多线程并行工作,减少垃圾回收的暂停时间,提高吞吐量。

  • CMS(Concurrent Mark - Sweep) :采用标记 - 清除算法,并且是并发的。CMS垃圾回收器在垃圾回收过程中,除了初始标记和最终标记阶段需要短暂的STW外,其余阶段(如并发标记和并发清除)可以与应用程序线程并发执行。这使得CMS能够在应用程序运行过程中进行垃圾回收,减少暂停时间。然而,CMS可能会产生内存碎片,并且在并发收集失败时需要使用其他垃圾回收器进行全堆回收。在Java 9中,CMS已被废弃。

(三)G1(Garbage First)垃圾回收器

  • 原理 :G1将堆内存划分为多个大小相等的区域(Region)。每个区域可以充当Eden区、Survivor区或老年代的一部分。G1根据垃圾回收的优先级选择区域进行回收,优先回收死亡对象较多的区域。

  • 特点 :能够预测垃圾回收的停顿时间,并在指定时间内完成垃圾回收任务。适用于大内存和对停顿时间有严格要求的应用场景。

  • 优势 :通过将堆划分为区域,G1可以灵活地进行垃圾回收,减少全堆扫描的可能性。同时,G1可以更好地平衡垃圾回收的吞吐量和暂停时间。

(四)ZGC(Z Garbage Collector)

  • 特点 :ZGC是Java 11中引入的一种低延迟垃圾回收器,其目标是将垃圾回收的暂停时间控制在10毫秒以内。ZGC采用了一系列先进的技术,如写屏障、内存映射等,以实现这一目标。

  • 适用场景 :适用于对延迟要求极高的场景,如实时交易系统、高频金融应用等。

选择合适的垃圾回收器和调整其参数对于优化Java应用程序的性能至关重要。不同的应用场景对吞吐量、延迟和暂停时间有不同的要求,因此需要根据具体情况进行选择和调整。

垃圾回收的性能优化实践

(一)调整新生代和老年代的大小

  • 新生代大小 :通过-XX:NewRatio参数可以调整新生代和老年代的比例。例如,-XX:NewRatio=3表示新生代占堆内存的1/4,老年代占3/4。增大新生代的大小可以减少Minor GC的频率,但可能会增加Minor GC的暂停时间;减小新生代的大小则相反。

  • 老年代大小 :通过-XX:MaxNewSize和-XX:MinNewSize参数可以设置新生代的最大和最小大小。合理调整新生代的大小可以确保老年代有足够的空间存储长期存活的对象,同时避免频繁的Major GC。

(二)优化TLAB的大小

  • TLAB的大小 :通过-XX:ThreadLocalAllocationBufferMaxSize参数可以设置TLAB的最大大小。增大TLAB的大小可以减少线程申请新TLAB的频率,提高内存分配效率;但过大的TLAB可能导致内存浪费。可以通过-XX:TLABSize参数设置TLAB的初始大小,并根据应用程序的实际情况进行调整。

(三)调整 Survivor 区的大小和晋升阈值

  • Survivor 区大小 :通过-XX:SurvivorRatio参数可以调整Eden区和Survivor区的比例。例如,-XX:SurvivorRatio=8表示Eden区的大小是每个Survivor区的8倍。增大Survivor区的大小可以容纳更多的存活对象,减少对象晋升到老年代的频率;但会减少Eden区的大小,可能增加Minor GC的频率。

  • 晋升阈值 :通过-XX:MaxTenuringThreshold参数可以设置对象在Survivor区中复制的最大次数。增大该值可以使对象在新生代中停留更长时间,减少对象晋升到老年代的频率;但可能会增加Minor GC的暂停时间。

(四)选择合适的垃圾回收器

  • 根据应用场景选择 :对于对吞吐量要求较高的批处理任务,可以选择Parallel Scavenge和Parallel Old的组合;对于对延迟敏感的用户交互型应用,可以选择G1或ZGC垃圾回收器。

  • 参数调优 :每种垃圾回收器都有许多可调参数,通过合理设置这些参数可以进一步优化垃圾回收的性能。例如,在G1中可以通过-XX:MaxGCPauseMillis参数设置最大垃圾回收暂停时间的目标值,JVM会根据该值自动调整垃圾回收的策略。

(五)监控和分析垃圾回收行为

  • 垃圾回收日志 :启用垃圾回收日志(如-XX:+PrintGC、-XX:+PrintGCDetails等)可以记录垃圾回收的详细信息,包括垃圾回收的次数、暂停时间、回收的内存大小等。通过分析这些日志,可以了解垃圾回收器的工作情况,发现性能瓶颈。

  • 性能分析工具 :使用性能分析工具(如JProfiler、VisualVM等)可以直观地查看应用程序的内存使用情况、垃圾回收活动、线程状态等信息。这些工具可以帮助开发者快速定位性能问题,进行有针对性的优化。

垃圾回收的未来发展趋势

随着Java技术的不断发展和应用场景的日益多样化,垃圾回收技术也在不断进化。未来,垃圾回收器将更加智能化、自动化,能够根据应用程序的运行时特性动态调整垃圾回收策略,减少人工调优的成本。例如,自适应调节算法可以根据应用程序的内存分配模式和垃圾回收开销,自动调整新生代和老年代的大小、垃圾回收器的类型等参数。此外,新型垃圾回收器(如Shenandoah、ZGC等)将继续优化延迟和吞吐量的平衡,满足对实时性和响应速度要求极高的应用场景的需求。同时,随着硬件技术的进步,如非易失性内存(NVM)的普及,垃圾回收器的设计也将充分考虑新硬件特性,进一步提升性能和效率。

总结

垃圾回收作为Java虚拟机自动内存管理的核心,其性能与效率对Java应用程序的整体表现有着举足轻重的影响。从基础的引用计数法与可达性分析,到复杂的卡表与写屏障机制,JVM的垃圾回收体系融合了多种算法与优化策略。需要通过深入了解垃圾回收的各个环节,才能够更加精准地优化程序性能,选择和配置最适合的垃圾回收器。

相关文章:

JVM——垃圾回收

垃圾回收 在Java虚拟机(JVM)的自动内存管理中,垃圾回收(Garbage Collection, GC)是其核心组件之一。它负责回收堆内存中不再使用的对象所占用的内存空间,以供新对象的分配使用。下面我们将深入探讨JVM中的…...

【AI News | 20250506】每日AI进展

AI Repos 1、gitsummarize GitSummarize是一个在线工具,用户只需将GitHub URL中的“hub”替换为“summarize”,即可为任何公开或私有代码库生成交互式文档。该工具利用Gemini分析代码结构,自动生成系统级架构概述、目录和文件摘要、自然语言…...

LabVIEW高冲击加速度校准系统

在国防科技领域,高 g 值加速度传感器广泛应用于先进兵器研制,如深侵彻系统、精确打击弹药及钻地弹药等。其性能指标直接影响研究结果的准确性与可靠性,因此对该传感器进行定期校准意义重大。高冲击加速度校准系统具备多方面功能,适…...

优化算法 - intro

优化问题 一般形式 minimize f ( x ) f(\mathbf{x}) f(x) subject to x ∈ C \mathbf{x} \in C x∈C 目标函数 f : R n → R f: \mathbb{R}^n \rightarrow \mathbb{R} f:Rn→R限制集合例子 C { x ∣ h 1 ( x ) 0 , . . . , h m ( x ) 0 , g 1 ( x ) ≤ 0 , . . . , g r …...

从PotPlayer到专业播放器—基于 RTSP|RTMP播放器功能、架构、工程能力的全面对比分析

从PotPlayer到专业播放器SDK:工程项目怎么选择合适的播放方案? ——基于 RTSP、RTMP 播放器功能、架构、工程能力的全面对比分析 在许多音视频项目早期,我们都听过这句话: “本地测试就用 PotPlayer 播吧,能播就行了…...

EasyRTC嵌入式音视频通信SDK技术,助力工业制造多场景实时监控与音视频通信

一、背景 在数字化时代,实时监控广泛应用于安防、工业、交通等领域。但传统监控系统实时性、交互性欠佳,难以满足需求。EasyRTC作为先进实时通信技术,具有低延迟、高可靠、跨平台特性,能有效升级监控系统。融入EasyRTC后&#xf…...

MPay码支付系统第四方聚合收款码多款支付插件个人免签支付源码TP8框架全开源

一、源码描述 这是一套码支付源码(MPay),基于TP8框架,前端layui2.9后端PearAdmin,专注于个人免签收款,通过个人的普通收款码,即可实现收款通知自动回调,支持绝大多数商城系统&#…...

wrod生成pdf。[特殊字符]改背景

import subprocess import os,time from rembg import remove, new_session from PIL import Image import io from docxtpl import DocxTemplate, InlineImage from docx.shared import Inches input_folder ‘tupian’ # 输入文件夹 kouchu_folder ‘kouchu’ # 去背景图像…...

动手学深度学习12.1. 编译器和解释器-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记,以及对课后练习的一些思考,自留回顾,也供同学之人交流参考。 本节课程地址:无 本节教材地址:12.1. 编译器和解释器 — 动手学深度学习 2.0.0 documentation 本节…...

数字文明时代开源技术驱动的商业范式重构:基于开源AI大模型、AI智能名片与S2B2C商城小程序源码的协同创新研究

摘要:数字文明时代,数字技术正以指数级速度重构全球经济与社会结构。本文聚焦开源AI大模型、AI智能名片与S2B2C商城小程序源码的协同创新机制,从技术架构、商业逻辑、实践案例三个维度展开系统研究。基于多行业实证数据,揭示开源技…...

【Bootstrap V4系列】学习入门教程之 组件-轮播(Carousel)

Bootstrap V4系列 学习入门教程之 组件-轮播(Carousel) 轮播(Carousel)一、How it works二、Example2.1 Slides only 仅幻灯片2.2 With controls 带控制装置2.3 With indicators 带指示器2.4 With captions 带字幕 轮播&#xff0…...

嵌入式openharmony标准鸿蒙系统驱动开发基本原理与流程

第一:鸿蒙概述 OpenHarmony采用多内核(Linux内核或者LiteOS)设计,支持系统在不同资源容量的设备部署。当相同的硬件部署不同内核时,如何能够让设备驱动程序在不同内核间平滑迁移,消除驱动代码移植适配和维护的负担,是OpenHarmony驱动子系统需要解决的重要问题。 …...

Leetcode 刷题记录 08 —— 链表第二弹

本系列为笔者的 Leetcode 刷题记录,顺序为 Hot 100 题官方顺序,根据标签命名,记录笔者总结的做题思路,附部分代码解释和疑问解答,01~07为C语言,08及以后为Java语言。 01 合并两个有序链表 /*** Definition…...

PaddlePaddle 和PyTorch选择与对比互斥

你遇到的错误信息如下: RuntimeError: (PreconditionNotMet) Tensors dimension is out of bound.Tensors dimension must be equal or less than the size of its memory.But received Tensors dimension is 8, memorys size is 0.[Hint: Expected numel() * Size…...

极新月报·2025.4人工智能投融资观察

“ AI投资从‘量’向‘质’过渡 ” 4月重点关注: 1、四月人工智能领域投融资事件105起,披露金额78.63亿人民币。 2、亿级人民币以上金额的投资事件共20起 。 3、四月人工智能领域出现1起IPO事件。 4、在所有融资事件里,除去股权投资&…...

C++ vector 介绍与使用

目录 1.vector是什么? 2.vector的使用 2.1vector的构造函数 2.2vector iterator 的使用 2.3vector 空间增长问题 2.4vector的增删查改 1.vector是什么? 1. vector是表示可变大小数组的序列容器。 2. 就像数组一样,vector也 采用连续的存储…...

可以下载blender/fbx格式模型网站

glbxz.com glbxz.com可以下载blender/fbx格式模型。当然里面有免费的...

Vi/Vim 编辑器详细指南

Vi/Vim 编辑器详细指南 简介一、模式详解1. 命令模式(Normal Mode)2. 插入模式(Insert Mode)3. 可视模式(Visual Mode)4. 命令行模式(Ex Mode)二、核心操作1. 保存与退出2. 导航与移动3. 编辑与文本操作4. 搜索与替换三、高级技巧1. 多文件与窗口操作2. 宏录制3. 寄存器…...

LeetCode 热题 100 22. 括号生成

LeetCode 热题 100 | 22. 括号生成 大家好,今天我们来解决一道经典的算法题——括号生成。这道题在 LeetCode 上被标记为中等难度,要求生成所有可能的并且有效的括号组合。这是一道非常经典的回溯法题目,非常适合用来练习递归和回溯的技巧。…...

UE5 MetaHuman眼睛变黑

第5个材质MI_EyeOcclusion_Inst修改成透明即可...

【C语言】--指针超详解(一)

目录 一.内存和地址 1.1--内存 1.2--如何理解编址 二.指针变量和地址 2.1--取地址操作符(&) 2.2--指针变量和解引用操作符(*) 2.2.1--指针变量 2.2.2--如何理解指针类型 2.2.3--解引用操作符 2.3--指针变量的大小 三.指针变量类型的意义 3.1--从指针的解引用方…...

高频工业RFID读写器-三格电子

高频工业RFID读写器 型号:SG-HF40-485、SG-HF40-TCP 产品功能 高频工业读写器(RFID)产品用在自动化生产线,自动化分拣系统,零部件组装产线等情境下,在自动化节点的工位上部署RFID读写设备,通过与制品的交互&#xf…...

驱动开发系列57 - Linux Graphics QXL显卡驱动代码分析(四)显示区域绘制

一:概述 前面在介绍了显示模式设置(分辨率,刷新率)之后,本文继续分析下,显示区域的绘制,详细看看虚拟机的画面是如何由QXL显卡绘制出来的。 二:相关数据结构介绍 struct qxl_moni…...

6.5 行业特定应用:金融、医疗、制造等行业的定制化解决方案

金融、医疗和制造行业作为全球经济支柱,面临数据复杂性、实时性需求和严格合规性的共同挑战,同时各行业因业务特性衍生出独特需求。金融行业需应对市场波动、欺诈风险和多国法规,医疗行业聚焦精准诊断和患者数据隐私,制造业则强调…...

【Linux我做主】深入探讨从冯诺依曼体系到进程

从冯诺依曼体系到进程 从冯诺依曼体系到进程github地址1. 前言2. 计算机硬件2.1 冯诺依曼体系结构2.2 冯诺依曼模型的三大要点2.3 从QQ聊天认识:冯诺依曼体系下数据是如何流动的?发送方数据流动接收方数据流动 3. 计算机软件的根基——操作系统3.1 操作系…...

idea更换jdk版本操作

有时候我们有更换jdk版本的问题,自己电脑可能有多个版本,下面来介绍修改jdk版本修改修改什么地方 1 2 3 4 5 6 再修改pom即可,还有环境变量即可,希望有帮到大家!...

npm install下载插件无法更新package.json和package-lock.json文件的解决办法

经过多番查证,使用npm config ls查看相关配置等方式,最后发现全局的.npmrc文件的配置多写了globaltrue,去掉就好了 如果参数很多,不知道是哪个参数引起的,先只保留registryhttp://xxx/,试试下载&#xff0…...

机器学习实操 第二部分 神经网路和深度学习 第13章 使用TensorFlow加载和预处理数据

机器学习实操 第二部分 神经网路和深度学习 第13章 使用TensorFlow加载和预处理数据 内容概要 第13章深入探讨了如何使用TensorFlow加载和预处理数据。本章首先介绍了tf.data API,它能够高效地加载和预处理大规模数据集,支持并行文件读取、数据打乱、批…...

WebSoket的简单使用

一、WebSocket简介 1.1、双向通信/全双工 客户端和服务器之间同时双向传输,全双工通信允许客户端和服务器随时互相发送消息,不需等一方发送请求后另一方才进行响应。 适用要低延迟/实时交互的场景,如在线游戏、即时通讯、股票行情等。 1.2…...

01_线性表

一、线性表的顺序存储 逻辑上相邻的数据元素,物理次序也相邻。占用连续存储空间,用“数组”实现,知道初始位置就可推出其他位置。 00_宏定义 // 函数结果状态代码 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #defin…...

STL详解 - map和set

目录 一、关联式容器概述 二、键值对 三、树形结构的关联式容器 (一)set 1. set的介绍 2. set的使用 (1)模板参数列表 (2)构造函数 (3)迭代器函数 (4&#xff…...

SpringBoot 集成滑块验证码AJ-Captcha行为验证码 Redis分布式 接口限流 防爬虫

介绍 滑块验证码比传统的字符验证码更加直观和用户友好,能够很好防止爬虫获取数据。 AJ-Captcha行为验证码,包含滑动拼图、文字点选两种方式,UI支持弹出和嵌入两种方式。后端提供Java实现,前端提供了php、angular、html、vue、u…...

高并发PHP部署演进:从虚拟机到K8S的DevOps实践优化

一、虚拟机环境下的部署演进 1. 低并发场景&#xff08;QPS<10&#xff09;的简单模式 # 典型部署脚本示例 ssh userproduction "cd /var/www && git pull origin master" 技术痛点&#xff1a; 文件替换期间导致Nginx返回502错误&#xff08;统计显示…...

vue引入物理引擎matter.js

vue引入物理引擎matter.js 在 Vue 项目中集成 Matter.js 物理引擎的步骤如下: 1. 安装 Matter.js npm install matter-js # 或 yarn add matter-js2. 创建 Vue 组件 <template><div ref="physicsContainer" class="physics-container"><…...

【实战项目】简易版的 QQ 音乐:一

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能自我实现简易版的 QQ 音乐。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a…...

部署Superset BI(三)连接HANA数据库

metabase和redash都不支持HANA数据库&#xff0c;选择superset就是看重这一点&#xff0c;开始尝试连接HANA数据库。 按Superset的技术文档&#xff1a;pip install hdbcli sqlalchemy-hana or pip install apache-superset[hana] --进入容器 rootNocobase:/usr/superset/supe…...

快速学会Linux的WEB服务

一.用户常用关于WEB的信息 什么是WWW www是world wide web的缩写&#xff0c;及万维网&#xff0c;也就是全球信息广播的意思 通常说的上网就是使用www来查询用户所需要的信息。 www可以结合文字、图形、影像以及声音等多媒体&#xff0c;超链接的方式将信息以Internet传递到世…...

如何搭建spark yarn模式集群的集群

以下是搭建 Spark YARN 模式集群的一般步骤&#xff1a; 准备工作 确保集群中各节点已安装并配置好 Java 环境&#xff0c;且版本符合 Spark 要求。规划好集群中节点的角色&#xff0c;如 Master 节点、Worker 节点等&#xff0c;并确保各节点之间网络畅通&#xff0c;能相互…...

端口安全基本配置

1.top图 2.交换机配置 交换机swa <SWA> system-view [SWA] vlan batch 10 20[SWA] interface GigabitEthernet0/0/1 [SWA-GigabitEthernet0/0/1] port link-type trunk [SWA-GigabitEthernet0/0/1] port trunk allow-pass vlan 10[SWA] interface GigabitEthernet0/0/2 …...

【JsonCpp、Muduo、C++11】JsonCpp库、Muduo库、C++11异步操作

JsonCpp库、Muduo库、C11异步操作 1. JsonCpp库1.1 Json数据格式1.2 JsonCpp介绍1.3 JsonCpp使用 2. Muduo库2.1 Muduo库常见接口介绍2.1.1 TcpServer类基础介绍2.1.2 EventLoop类基础介绍2.1.3 TcpConnection类基础介绍2.1.4 Buffer类基础介绍2.1.5 TcpClient类基础介绍 2.2 M…...

【自然语言处理与大模型】LlamaIndex的词嵌入模型和向量数据库

&#xff08;1&#xff09;嵌入模型的定义和作用 嵌入模型&#xff08;Embedding Model&#xff09;的本质在于将高维的、稀疏的数据转换为低维的、密集的向量表示&#xff0c;使得这些向量能够在数学空间中表达原始数据的语义信息。作用如下&#xff1a; 降维表示&#xff1a;…...

SLAM算法工程师面经大全:2025年面试真题解析与实战指南

SLAM算法工程师面经大全&#xff1a;2025年面试真题解析与实战指南 一、SLAM技术概述与核心原理 1&#xff0e;SLAM基础理论框架 SLAM算法的核心在于同步定位与建图&#xff0c;这一过程涉及传感器数据融合、运动建模与优化方法。在传感器数据融合方面&#xff0c;不同类型的…...

虚拟现实视频播放器 2.6.1 | 支持多种VR格式,提供沉浸式观看体验的媒体播放器

虚拟现实媒体播放器是一款专为在智能手机上播放VR&#xff08;虚拟现实&#xff09;照片和视频而设计的应用程序。它支持多种格式的影像内容&#xff0c;包括360和180等距矩形柱面、标准镜头和鱼眼镜头拍摄的照片和视频&#xff0c;并且兼容3D立体并排、上/下以及收缩媒体格式。…...

从黔西游船侧翻事件看极端天气预警的科技防线——疾风气象大模型如何实现精准防御?

近日,贵州省黔西市一起载人游船侧翻事故令人痛心。调查显示,事发时当地突遇强风暴雨,水面突发巨浪导致船只失控。这一事件再次凸显:在极端天气频发的时代,传统“经验式防灾”已不足够,唯有依靠智能化的气象预警技术,才能筑牢安全底线。 极端天气预警的痛点:为什么传统方…...

颠覆监测体验!WM102无线温湿度记录仪开启智能物联新时代

当温湿度失控成为企业隐形成本杀手&#xff0c;您是否还在用传统设备疲于应对&#xff1f;一款集智能、精准、全能于一身的神器横空出世——WM102无线温湿度记录仪&#xff0c;用硬核科技重新定义环境监测&#xff01; ▌5大场景痛点 一招破解 无论是医药冷库里的疫苗守护战&am…...

Linux云服务器配置git开发环境

文章目录 1. 安装 git2. git clone3. git add .4. git commit -m 提交记录5. git push&#x1f351; 异常原因&#x1f351; 解决办法 6. git pull7. git log8. git rm9. git mv10. git status 1. 安装 git sudo yum install git -y2. git clone 此命令的作用是从远程仓库把代…...

山东大学软件学院项目实训-基于大模型的模拟面试系统-个人主页头像上传

采用图床的方案&#xff0c;存储用户头像。 实现步骤 引入OSS依赖 在我们的SpringBoot项目中引入OSS依赖 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version> &l…...

AI智能体|扣子(Coze)实战【天气查询插件开发教程】

大家好&#xff0c;我是偶然&#xff0c;AI洞察&#xff0c;AI智能体&#xff0c;AI实战案例分享 今天教大家用 Coze 开发一个天气插件&#xff0c;本来我是想教大家怎么用 AI 写代码节点实现节点功能的&#xff0c;但是我感觉太复杂了。 起码来说&#xff0c;我还没做到用特别…...

VBA ListBox/ComboBox 响应鼠标滚轮操作

一般情况下&#xff0c;在Excel的vba窗口中&#xff0c;我们是无法使用鼠标滚轮控制例如 ListBox 和 ComboBox 控件的。我们只能通过鼠标点击的方式来逐个选择选项。 我们都知道&#xff0c;通过鼠标滚轮快速的上下滚动候选项&#xff0c;以快速的定位选择选项&#xff0c;这是…...

Linux 更改内存交换 swap 为 zram 压缩,减小磁盘写入

1、查看当前 swap 的方式 swapon --show 我这里是默认的 swap 文件&#xff0c;大小为 2G。 2、安装 zram Ubuntu 下&#xff1a; sudo apt install zram-tools安装后默认会启动&#xff1a; 3、关闭默认的 swap 文件 sudo swapoff /swapfile 其次是关闭 /etc/fstab 中的 …...