【JVM-1】JVM内存结构

目录

  • 什么是JVM
  • Java源码执行机制
    • class文件的组成部分
  • JVM跨平台原理
  • JVM的组成
      • 年轻代与老年代
      • 对象分配过程
        • GC类型
          • Full GC触发条件:
          • 对象进入老年代的触发条件
        • 对象分配过程:
      • 字符串常量池
      • 静态变量
      • 线程本地分配缓冲区(TLAB)
        • TLAB相关参数:
        • 使用TLAB的原因:
      • 堆内存常用参数
    • 方法区(Method Area)
      • 方法区与堆,如图所示:
      • 元空间相关参数:
      • 类信息
      • 运行时常量池
    • 虚拟机栈(VM Stack)
      • 栈与栈帧
      • 局部变量表
      • 操作数栈
      • 动态链接
        • 方法引用:
        • 绑定机制:
        • 栈顶缓存:
      • 方法返回地址
    • 程序计数器(Program Counter Register)
      • 程序计数器特点:
    • 本地方法栈(Native Method Stack)
      • 本地方法栈特点:
  • 附:JVM结构图

什么是JVM

  • JVM(Java虚拟机)是一种计算机软件,它是Java编程语言的运行环境。
  • JVM可以在各种操作系统上运行,它负责解释和执行Java字节码,并提供了一种使Java程序能够与特定操作系统和硬件交互的方式。
  • JVM也提供了垃圾回收功能,用于管理和释放程序中不再使用的内存。
  • JVM的设计使得Java程序具有平台无关性,即可以在不同的操作系统和硬件上运行,只需安装适当版本的JVM即可。

Java源码执行机制

  • Java源代码是不能直接被机器识别的,需要先经过编译器编译成JVM可以执行的.class字节码文件,再由解释器解释运行。
  • Java源文件(.java) – Java编译器 --> Java字节码文件 (.class) – Java解释器 --> 执行。
  • 字节码文件(.class)是平台无关的。
  • Java中字符只以一种形式存在:Unicode。字符转换发生在JVM和OS交界处(Reader/Writer)。
    在这里插入图片描述

class文件的组成部分

  • 结构信息:包括class文件格式版本号及各部分的数量与大小的信息
  • 元数据:对应于Java源码中声明与常量的信息。包含类/继承的超类/实现的接口的声明信息、域与方法声明信息和常量池
  • 方法信息:对应Java源码中语句和表达式对应的信息。包含字节码、异常处理器表、求值栈与局部变量区大小、求值栈的类型记录、调试符号信息

JVM跨平台原理

在这里插入图片描述

JVM跨平台原理是基于字节码的。

  • Java源代码在编译时会被编译器转换为Java字节码(.class文件),而不是直接编译成机器码。这个字节码是一种中间代码,它可以在任何装有JVM的平台上运行。

  • 当Java程序被执行时,JVM会解释和执行这些字节码。JVM会将字节码翻译成特定平台的机器码,这个过程叫做即时编译(Just-In-Time Compilation)。即时编译器会将频繁执行的热点代码(Hotspot Code)编译成机器码,从而提高程序的执行效率。

  • 由于不同操作系统和硬件体系结构的差异,JVM需要针对不同平台提供特定的实现。这些不同平台上的JVM实现负责将字节码翻译成特定平台的机器码,并提供相应的运行时环境。

  • 这种通过将Java程序编译为字节码,在运行时使用JVM将字节码翻译为特定平台的机器码的方式,使得Java程序具有了跨平台的能力。只要有适当版本的JVM,Java程序就可以在任何支持JVM的平台上运行。

JVM的组成

在这里插入图片描述

JVM(Java Virtual Machine,Java虚拟机)是Java程序的运行环境,它具有以下几个主要的结构组成部分:

  1. 类加载器(Class Loader):负责将Java字节码文件加载到JVM中。类加载器将字节码文件加载到内存,并转换为JVM内部的数据结构,以供JVM执行。

  2. 执行引擎(Execution Engine):负责执行JVM中加载的字节码文件。执行引擎将字节码文件解释为机器码,并执行对应的指令。

  3. 内存区域(Memory Area):JVM将内存划分为不同的区域,用于存储不同类型的数据。主要包括:

    • 堆(Heap):存放Java对象实例和数组。
    • 方法区(Method Area):存放已加载的类的信息、常量池、静态变量等。
    • 栈(Stack):存放方法的调用栈帧和方法局部变量。
    • 程序计数器(Program Counter Register):保存当前线程执行的字节码指令地址。
    • 本地方法栈(Native Method Stack):执行本地方法的栈。
  4. 垃圾收集器(Garbage Collector):负责自动回收不再使用的内存。垃圾收集器会识别并释放不再被引用的对象,以便后续的内存分配。

  5. JNI(Java Native Interface):允许Java代码调用本地代码或者本地代码调用Java代码。JNI提供了一组接口,用于在Java和本地代码之间进行交互。

这些组成部分共同构成了JVM的结构,使得Java程序可以跨平台运行,并且具有自动内存管理等特性。

  • JVM堆(Heap)是Java虚拟机中的一块内存区域(所有线程共享),主要用于存储对象实例和数组。
  • 堆被划分为三个部分:年轻代、老年代和永久代(在JDK8中取消了永久代)
  • 其中,年轻代又被划分为Eden区、Survivor区(含:S0和S1)。
    在这里插入图片描述

堆的特点:

  • 堆内存最大
  • 堆是被线程共享,
  • 堆的目的就是存放对象,几乎所有的对象实例都在此分配。当然,随着优化技术的更新,某些数据也会被放在栈上等。

因为堆占用内存空间最大,堆也是Java垃圾回收的主要区域(重点对象),因此也称作“GC堆”(Garbage Collected Heap)
在这里插入图片描述

年轻代与老年代

  • 在年轻代中,大部分对象朝生夕死,因此,年轻代的设计目标是尽可能地减少对象的存活时间,以便更快地回收内存。
  • 默认情况下,年轻代和老年代的比例为1:2,即:年轻代占整个堆空间的1/3,老年代占整个堆空间的2/3。
  • 可以通过参数-XX:NewRatio=<n>来调整年轻代和老年代的比例。
    • 其中<n>表示老年代和年轻代的比例,默认值为2。
    • 如:设置-XX:NewRatio=2,表示老年代占整个堆空间的2/3,年轻代占整个堆空间的1/3。
  • 可以通过参数-XX:SurvivorRatio=<n>来调整Eden区和Survivor区的比例大小。
    • 其中<n>表示Eden区和一个Survivor区的比例,默认值为8。
    • 如:设置-XX:SurvivorRatio=8,表示Eden区与Survivor区的比例为8:1:1。

对象分配过程

在分析对象分配过程之前,先简单说明一下GC类型

GC类型
  • Minor GC(又称Young GC):主要用于收集年轻代中的非存活对象。Minor GC在Eden区空间不足时触发。注意:Minor GC可能会引发STW(Stop The World,即暂停用户线程)。

  • Major GC:主要用于收集老年代中的非存活对象。Major GC在老年代空间不足时触发。注意:Major GC一般都会伴随一次Minor GC,Major GC的速度一般会比Minor GC慢10倍,因此,STW的时间会更长(应尽量避免Minor GC)。目前只有CMS会有单独收集老年代的行为。

  • Mixed GC(混合收集):主要用于收集年轻代以及部分老年代中的非存活对象。目前只有G1 GC会有这种行为。

  • Full GC:主要用于收集整个堆(含:年轻代和老年代)中的非存活对象,即:Major GC+Minor GC组合。

Full GC触发条件:
  • 调用System.gc()方法时,可通过参数-XX:+ DisableExplicitGC来禁止调用System.gc()。
  • 方法区空间不足时。
  • Minor GC后,存活对象的大小超过了老年代的剩余空间。
  • Minor GC时,年轻代Survivor区空间不足,判断是否允许担保失败,不允许则触发Full GC。允许并且每次晋升到老年代的对象平均大小>老年代最大可用连续内存空间,也会触发Full GC。
  • CMS GC异常且CMS运行期间预留的内存无法满足程序需要时,抛出Concurrent Mode Failure异常,将CMS退化成Serial Old并触发Full GC。
对象进入老年代的触发条件
  • 对象的年龄达到15岁时。默认的情况下,对象经过15次Minor GC后会被转移到老年代中。对象进入老年代的Minor GC次数可以通过JVM参数:-XX:MaxTenuringThreshold进行设置,默认为15次。
  • 动态年龄判断。当一批存活对象的总大小超过Survivor区内存大小的50%时,按照年龄的大小(年龄大的存活对象优先转移)将部分存活对象转移到老年代中。
  • 大对象直接进入老年代 。当需要创建一个大于年轻代剩余空间的对象(如:一个超大数组)时,该对象会被直接存放到老年代中,可以通过参数-XX:PretenureSizeThreshold(默认值是0,即:任何对象都会先在年轻代分配内存)进行设置。
  • Minor GC后的存活对象太多无法放入Survivor区时, 会将这些对象直接转移到老年代中。
对象分配过程:
  • 新生成的对象在年轻代Eden区中分配内存,当Eden空间已满时,触发Minor GC,将不再被其他对象所引用的对象进行回收,存活下来的对象被转移到Survivor0区。
  • Survivor0区满后触发Minor GC,将Survivor0区存活下来的对象转移到Survivor1区,同时,清空Survivor0区,保证总有一个Survivor区为空。
  • 经过多次Minor GC后,仍然存活的对象被转移到老年代,进入老年代的Minor GC次数可以通过参数-XX:MaxTenuringThreshold=<N>进行设置,默认为15次。
  • 当老年代已满时会触发Major GC(即:Full GC,因此执行Major GC时会先执行Minor GC)。

分代收集的原因:将对象按照存活概率进行分类,主要是为了减少扫描范围和执行GC的频率,同时,对不同区域采用不同的回收算法,提高回收效率。

年轻代中存在两块相同大小的Survivor区的原因:解决内存碎片化,即:保证分配对象(如:大对象)时有足够的连续内存空间。

字符串常量池

  • 字符串常量池是Java中的一个特殊的存储区域,用于存储字符串常量。
  • 在Java中,字符串常量是不可变的,因此可以被共享。
  • 这样可以减少内存的使用,提高程序的性能。
  • 在JDK8中,字符串常量池存储在堆中。

静态变量

  • 静态变量是指在类中定义的变量,它们的值在整个程序运行期间都不会改变。
  • 在JDK8中取消了永久代,方法区变成了一个逻辑上的区域,因此,静态变量的内存在堆中进行分配(JDK7及以前,静态变量的内存在永久代中进行分配)。
  • 它们的生命周期与类的生命周期相同。

线程本地分配缓冲区(TLAB)

  • TLAB(Thread Local Allocation Buffer)是Java虚拟机中的一个优化技术,主要用于提高对象的分配效率。
  • 每个线程都有自己的TLAB,用于分配对象。
  • 当一个线程需要分配对象时,它会先在自己的TLAB中分配,如果TLAB中的空间不足,则会向堆中申请空间。
TLAB相关参数:
  • 参数-XX:UseTLAB:设置TLAB启动或关闭,默认开启。
  • 参数-XX:TLABWasteTargetPercent:设置TLAB所占用Eden区空间的百分比。
使用TLAB的原因:
  1. 保证创建对象时线程安全。堆(Heap)是线程共享区域,在并发环境下,对象在堆中分配内存时存在线程安全问题。通过使用TLAB(无锁方式)解决多个线程同时操作同一地址带来的线程安全问题。
  2. 提高对象的内存分配效率。在堆(Heap)中创建对象非常频繁,在并发环境下,通过加载机制为对象在堆中分配内存时会影响内存分配速度。通过使用TLAB(无锁方式)提高对象的内存分配效率。

堆内存常用参数

参数描述
-Xms堆内存初始大小,单位为m、g
-Xmx(MaxHeapSize)堆内存最大允许大小,一般不要超过物理内存的80%
-XX:PerSize非堆内存初始大小,一般应用设置初始化200m、最大1024m即可
-XX:MaxPerSize非堆内存最大允许大小
-XX:NewSize(-Xns)年轻代内存初始大小
-XX:MaxNewSize(-Xmn)年轻代内存最大允许大小
-XX:SurvivorRatio=8年轻代中Eden区与Survivor区的容量比例值,默认为8,即8:1:1
-Xss虚拟机栈内存大小

方法区(Method Area)

  • 在JDK8及之前,方法区属于永久代,而在JDK8之后,永久代被移除,方法区被移到了本地内存中,即:元空间(Meta Space)。
  • 元空间逻辑上属于堆的一部分,但是为了与堆进行区分,通常又叫非堆。元空间是各个线程共享的内存区域,它主要存储两部分内容:
    • 类信息。
    • 运行时常量池。

方法区与堆,如图所示:

在这里插入图片描述

元空间相关参数:

  • MetaspaceSize :初始化元空间大小,控制发生GC阈值,默认值为20MB。
  • MaxMetaspaceSize : 限制元空间大小上限,防止异常占用过多物理内存,默认值为-1(表示无限制)。

类信息

类信息指的是加载到方法区中的Class文件信息,Class文件信息中除了有类的版本、字段、方法、接口等描述信息外, 还包含一项常量池表(又称静态常量池)信息,常量池表主要用于存放编译器生成的各种静态常量(又称字面常量或字面量)和符号引用。

  • 静态常量:指由字母、数字等构成的字符串或者数字常量。静态常量只可以右值出现,右值指的是赋值时等号右边的值,如:int a=1,a为左值,1为右值。
  • 符号引用:符号引用主要包括以下三类常量:
    • 类和接口的全限定名。
    • 字段的名称和描述符。
    • 方法的名称和描述符。

运行时常量池

运行时常量池主要用于程序运行时为常量池表中的静态变量、符号引用等静态信息分配内存地址。

虚拟机栈(VM Stack)

  • 虚拟机栈为线程私有,它描述的是Java方法执行的内存模型。
  • 每个栈由多个栈帧(Stack Frame)组成,每个方法被执行时,Java虚拟机都会同步创建一个栈帧用于存储该方法的局部变量表、操作数栈、动态链接、方法返回地址等信息。

栈与栈帧

  • 每一个方法从被调用到执行完毕的过程,对应着一个栈帧在虚拟机栈中从入栈到出栈的过程
  • 栈顶的栈帧是当前执行方法,当这个方法调用其他方法时会创建一个新的栈帧,这个新的栈帧会被放到虚拟机栈的栈顶,变为当前活动栈帧,该栈帧所有指令都完成后,会将其从栈中移除,之前的栈帧变为当前活动栈帧,前面移除栈帧的返回值变为当前活动栈帧的一个操作数。
    在这里插入图片描述
    栈帧包含局部变量表、操作数栈、动态连接、方法返回地址等。

局部变量表

  • 局部变量表是一组变量值的存储空间,用于存放方法参数和方法内部定义的局部变量。
  • 在将Java文件编译成Class文件时,会在方法的Code属性的max_locals数据项中确定局部变量表所需要分配的最大容量。
  • 局部变量表的容量以变量槽(Slot)为最小单位,32位虚拟机中一个Slot可以存放32位(4字节)以内的数据类型(boolean、byte、char、short、int、float、reference以及returnAddress)。
  • 对于64位长度的数据类型(long,double),虚拟机会以高位对齐方式为其分配两个连续的Slot空间(即:将long和double数据类型读写分割成为两次32位读写)。
  • 对于reference类型,虚拟机规范没有明确说明它的长度,但虚拟机一般可以从此引用中直接或者间接地查找到对象在Java堆中的起始地址索引和方法区中的对象类型数据。
  • 为了尽可能节省栈帧空间,Slot被设计成可以重用,即:当程序计数器的指令已经超出了某个变量的作用域(执行完毕),这个变量对应的Slot就可以交给其他变量使用。但是这个机制会影响到GC,如:存在一个方法占用较多的Slot,执行完该方法的作用域后没有对Slot赋值或者清空,垃圾回收器便不能及时回收该Slot的内存。
  • 系统不会为局部变量赋予初始值(实例变量和类变量都会被赋予初始值)。

操作数栈

  • 每一个独立的栈帧中除了包含局部变量表以外,还包含一个后进先出(Last-In-First-Out)的操作数栈,操作数栈主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。

  • 当一个方法开始执行时,该方法中的操作数栈为空,在方法执行过程中,会有各种字节码指令向操作数栈中写入和提取内容(即:入栈和出栈)。

  • 如:通过操作数栈来进行算术运算、通过操作数栈来进行调用方法时的参数传递等。

  • 操作数栈和局部变量表一样,在将Java文件编译成Class文件时,在方法的Code属性的max_stack数据项中确定操作数栈所需要分配的最大容量。

  • 每一个操作数栈都会拥有一个明确的栈深度用于存储数值,32位数据类型占用一个栈单位深度,64位数据类型占用两个栈单位深度。

  • 操作数栈和局部变量表在访问方式上存在着较大差异,操作数栈并不是采用访问索引的方式进行数据访问,而是通过标准的入栈和出栈操作来完成一次数据访问。

  • 如果被调用的方法存在返回值,其返回值将会被压入当前栈帧的操作数栈中,并更新PC寄存器中下一条需要执行的字节码指令。

  • 在概念模型中,栈帧之间相互独立,大多数虚拟机都会做一些优化处理,使两个栈帧的局部变量表和操作数栈之间有部分重叠,这样在进行方法调用时可以直接共用参数,而不需要进行额外的参数复制。

动态链接

  • 每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用,包含这个引用的目的是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)。
  • 在将Java文件编译成Class文件时,所有的变量和方法引用都作为符号引用(Symbolic Reference)保存在Class文件的常量池中。
  • 比如:描述一个方法调用其他方法就是通过常量池中指向该方法的符号引用来表示,动态链接的作用就是将这些符号引用转换为调用方法的直接引用。
    在这里插入图片描述
方法引用:
  • 静态链接:当一个字节码文件被装载进JVM内部时,如果被调用的目标方法在编译期确定,且运行期保持不变时,这种情况下将调用方法的符号引用转换为直接引用的过程称之为静态链接。
  • 动态链接:如果被调用的方法在编译期无法确定,只能在程序运行期将调用方法的符号引用转换为直接引用,由于这种引用转换过程具备动态性,因此也被称之为动态链接。
绑定机制:

绑定指的是一个字段、方法或者类在符号引用被替换为直接引用的过程,这仅仅发生一次。静态链接和动态链接对应的方法的绑定机制为:早期绑定(Early Binding)和晚期绑定(Late Binding)。

  • 早期绑定:早期绑定就是指被调用的目标方法如果在编译期可知,且运行期保持不变时,即可将这个方法与所属的类型进行绑定。由于明确了被调用的目标方法,也就可以使用静态链接的方式将符号引用转换为直接引用。
  • 晚期绑定:如果被调用的方法在编译期无法确定,只能在程序运行期根据实际的类型绑定相关的方法,这种绑定方式也就被称之为晚期绑定。
栈顶缓存:
  • 由于操作数存储在内存中,频繁的执行内存读/写操作必然会影响执行速度。
  • 为了解决这个问题,HotSpot JVM设计者们提出了栈顶缓存技术,将栈顶元素全部缓存在物理 CPU的寄存器中,以此降低对内存的读/写次数,提升执行引擎的执行效率。

方法返回地址

  • 存放调用该方法的PC寄存器的值。一个方法的结束,有两种方式:

    • 正常执行完成。
    • 出现未处理的异常,非正常退出。
  • 无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的PC计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而方法异常退出时,返回地址需要通过异常表来确定,栈帧中一般不会保存这部分信息。

  • 正常完成出口和异常完成出口的区别在于:通过异常完成出口退出的方法不会给上层调用者产生任何的返回值。

程序计数器(Program Counter Register)

  • 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。
  • 在虚拟机的概念模型中,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖程序计数器来完成。
    在这里插入图片描述

程序计数器特点:

  • 每个线程都有一个独立的程序计数器,各线程之间计数器互不影响,独立存储。
  • 执行Java方法时,程序计数器的值不为空;执行Native本地方法时,程序计数器的值为空(Undefined)。
  • 程序计数器是唯一一个在Java虚拟机规范中没有规定任何内存溢出情况的区域。

本地方法栈(Native Method Stack)

  • 本地方法栈与虚拟机栈类似,不同的是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。
  • 在Java程序调用Native方法时,Native方法所需要的内存空间在本地方法栈中开辟。

本地方法栈特点:

  • 本地方法栈为线程私有。
  • 本地方法栈允许被实现成固定或者是可动态扩展的内存大小:
    • 固定内存大小,当线程请求分配的栈容量超过本地方法栈允许的最大内存大小时,Java虚拟机会抛出StackOverflowError异常。
    • 可动态扩展内存大小,当本地方法栈尝试扩展时无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的本地方法栈,Java虚拟机会抛出OutOfMemoryError异常。
  • Native方法一般由C/C++实现,它的具体做法是先在本地方法栈中登记Native方法,然后在执行引擎中加载本地方法库并执行。

附:JVM结构图

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot前后端传递数据时常用的JSON格式数据是什么?【讲解JSON概念、语法、以及Java对象互转】

SpringBoot前后端传递数据时常用的JSON格式数据是什么&#xff1f; JSON概念JSON语法JSON的两种结构&#xff1a;JSON字符串和Java对象互转&#xff1a;objectMapper.writeValueAsString(person);objectMapper.readValue(jsonStr,Person.class); 在SpringMVC框架中&#xff0c;…

【GitOps】使用Google工具JIB实现本地无需安装容器推送镜像,加速SpringCloud项目开发

文章目录 一、效果展示二、简介三、安装Jib插件1、区分环境2、安装插件一、效果展示 本地是window系统,无docker环境,没有任何runtime,使用jib工具打包镜像并推送完成,用时20秒 二、简介 Jib 是 Google 开发的一款开源工具,旨在帮助 Java 开发者更高效地将 Java 应用程…

ZNB40 矢量网络分析仪

ZNB40 矢量网络分析仪 100kHz至40GHz的宽频率范围&#xff0c;具有四个端口和附加信号发生器 概述 R&SZNB40 提供 100 kHz 至 40 GHz 的宽频率范围&#xff0c;具有四个端口和附加信号发生器。 罗德与施瓦茨带四个端口和附加内部信号源的 40 GHz 中档矢量网络分析仪&…

Ubuntu20.04安装python2和python3及版本配置

Ubuntu20.04安装python2和python3及版本配置_ubuntu 20.04 python3-CSDN博客https://blog.csdn.net/pangc2014/article/details/117407413 >>>ubuntu 安装源码python2_mob649e8161c39d的技术博客_51CTO博客https://blog.51cto.com/u_16175489/7327966

【Academy】测试WebSockets安全漏洞Testing for WebSockets security vulnerabilities

测试WebSockets安全漏洞Testing for WebSockets security vulnerabilities 概述WebSockets是什么?HTTP和WebSockets有什么区别&#xff1f;如何建立WebSocket连接&#xff1f;WebSocket消息看起来像什么&#xff1f; 操纵WebSocket流量拦截和修改WebSocket消息重放和生成新的W…

ONLYOFFICE 8.1:引领桌面办公新潮流,功能升级全面提升

目录 一、ONLYOFFICE是什么&#xff1f; 二、功能完善的PDF编辑器 三、幻灯片版式升级 四、改进从右至左显示 五、新的本地化选项 六、多媒体功能增强 七、应用价值探讨 一、ONLYOFFICE是什么&#xff1f; ONLYOFFICE 是一款功能强大的办公套件&#xff0c;旨在提供全面…

什么是云服务器镜像,如何选择?

云服务器镜像是一种用于业务连续性、灾难恢复和备份的技术手段&#xff0c;其本质是云端创建的服务器数据副本。 这些镜像内容可以涵盖系统、光盘、软件、网站甚至整个服务器&#xff0c;主要用于创建容错和冗余服务器计算基础架构&#xff0c;为用户提供了一个方便且可靠的解…

YOLOv8改进 | 注意力机制 | 轻量级的空间组增强模块SGE【全网独家】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录&#xff1a;《YOLOv8改进有效涨…

python项目运营时,出现,redis用户密码未设置问题,排查解决

一、问题描述&#xff1a; 在本地化开发过程中&#xff0c;pythonDjango运行项目&#xff0c;redis为本地windows版本&#xff0c;在设置过密码后&#xff0c;仍然会出现pythonDjango运行项目&#xff0c;终端日志显示如下&#xff1a; INFO info信息 ERROR redis数据库异常[&…

内网安全【4】SSH隧道技术

1.四大隧道协议 (1)SMB协议 判断&#xff1a;445端口是否开放 (2)ICMP协议 判断&#xff1a;ping命令能通说明使用icmp协议 (3)DNS协议 判断&#xff1a;nslookup www.baidu.com 属于UDP iodine工作原理是 &#xff0c;通过TAP虚拟网卡&#xff0c;在服…

大厂面试经验分享,小白如何在面试中脱颖而出

前言 毕业季&#xff0c;对于每一位即将步入社会的学子来说&#xff0c;都是一个充满挑战和机遇的时刻。作为我的一位好朋友也是好学长&#xff0c;他刚刚在一家顶尖科技公司斩获了他梦寐以求的职位。他深知求职路上的艰辛&#xff0c;因此打算把自己的经验分享给大家&#xf…

一键掌握多渠道推广效果!Xinstall超级渠道功能,让你的App推广更高效

在App运营的大潮中&#xff0c;如何高效、精准地推广App&#xff0c;成为每一位运营者关注的焦点。传统的推广方式&#xff0c;如地推、代理、分销、广告等&#xff0c;虽然能够带来一定的用户增长&#xff0c;但如何衡量推广效果、如何与合作伙伴结算、如何管理下属渠道等问题…

Java程序递归及mybatis递归查询

之前项目组有个需求&#xff0c;定时同步机构的信息。已知三方接口由于返回数据量很大&#xff0c;所以最后需要三方提供一个可根据机构编号获取当前机构及子机构信息的接口。而不是一次性返回全部机构信息&#xff01; 由于这次需求也用到了递归&#xff0c;所以记录下&#…

2024.6.26 刷题总结

2024.6.26 **每日一题** 526.优美的排列&#xff0c;该题考察的是状压dp的知识&#xff0c;用一个n位的二进制数表示排列中的数被选取的情况&#xff0c;若为1&#xff0c;则表示该位被选取&#xff0c;若为0&#xff0c;则表示该位没有被选取&#xff0c;用一个数组来存储当前…

【Vue】集成富文本编辑器

这文章使用的是wangeditor插件&#xff0c;官网地址&#xff1a;wangEditor&#xff0c;这个比较简单 安装 npm i wangeditor --save 使用 <div id"editor"></div>import E from "wangeditor"const editor new E("#editor") e…

兰州市红古区市场监管管理局调研食家巷品牌,关注细节,推动进步

近日&#xff0c;兰州市红古区市场监管管理局临平凉西北绿源电子商务有限公司进行了深入视察&#xff0c;为企业发展带来了关怀与指导。 食家巷品牌作为平凉地区特色美食的代表之一&#xff0c;一直以来凭借其纯手工工艺和独特的风味&#xff0c;在市场上占据了一席之地。领导…

charls抓包工具 mumu模拟器抓包apk

1.先安装mumu 官网添加链接描述 2.配置 设置&#xff0c;点进互联网&#xff0c;点编辑&#xff0c;选择手动代理 主机名写自己电脑的ip地址&#xff0c;端口随便&#xff0c;只要不被占用&#xff0c;一般参考其他人都是8888 3.下载charls 参考这个添加链接描述 先官网…

一文详解:什么是企业邮箱?最全百科

什么是企业邮箱&#xff1f;企业邮箱即绑定企业自有域名作为邮箱后缀的邮箱&#xff0c;是企业用于内部成员沟通和客户沟通的邮箱系统。 一、企业邮箱概念拆解 1.什么是企业邮箱&#xff1f; 企业邮箱即使用企业域名作为后缀的邮箱系统。它不仅提供专业的电子邮件收发功能&a…

How to persist LangChain conversation memory (save and load)

题意&#xff1a;如何持久化 LangChain 对话记忆&#xff08;保存和加载&#xff09; 问题背景&#xff1a; Im creating a conversation like so: 我正在创建一个对话&#xff0c;如下所示&#xff1a; llm ChatOpenAI(temperature0, openai_api_keyOPENAI_API_KEY,…

大学生毕业季,寄物流快递避雷指南

随着毕业季的来临&#xff0c;大学生们纷纷开始整理自己的行李&#xff0c;准备离开校园&#xff0c;踏入社会。 在这个过程中&#xff0c;寄送快递成为了一个不可或缺的环节。然而&#xff0c;在寄送快递的过程中&#xff0c;如果不注意一些细节&#xff0c;很容易遭遇各种“…