JVM的内存结构详解「重点篇」

一、JVM虚拟机数据区

· 虚拟机栈

        1、  线程私有

        2、 每个方法被执行的时候都会创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用的过程就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。

        3、栈帧: 是用来存储数据和部分过程结果的数据结构

        4、 栈帧大小确定时间: 编译期确定,不受运行期数据影响

        5、虚拟机栈的生命周期和线程是相同

        6、虚拟机栈是一个后入先出的栈。栈帧是保存在虚拟机栈中的,栈帧是用来存储数据和存储部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)

        7、线程运行过程中,只有一个栈帧是处于活跃状态,称为“当前活跃栈帧”,当前活动栈帧始终是虚拟机栈的栈顶元素:如图->

        8、栈帧细节如图:

 

        9、局部变量表是一组局部变量值存储空间,用于存放方法参数和方法内部定义的局部变量。在Java文件编译为Class文件时,就在方法表的Code属性的max_locals数据项中确定了该方法需要分配的最大局部变量表的容量 

        10、操作数栈也常被称为操作栈,它是一个后入先出栈。JVM底层字节码指令集是基于栈类型的,所有的操作码都是对操作数栈上的数据进行操作,对于每一个方法的调用,JVM会建立一个操作数栈,以供计算使用。和局部变量一样。操作数栈的最大深度也是编译的时候写入到方法表的code属性的max_stacks数据项中。操作数栈的每一个元素可以是任意的Java数据类型,包括long、double。32位数据类型所占的栈容量为1,64位数据类型所占的栈容量为2。栈容量的单位为“字宽”,对于32位虚拟机来说,一个“字宽”占4个字节,64位虚拟机来说,一个“字宽”占8个字节。当一个方法刚刚执行的时候,这个方法的操作数栈是空的,在方法执行的过程中,会有各种字节码指向操作数栈中写入和提取值,也就是入栈与出栈操作

        11、每个栈帧都包含一个指向运行时常量池中该栈帧所属性方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。在Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。这些符号引用一部分会在类加载阶段或第一次使用的时候转化为直接引用,这种转化称为静态解析。另外一部分将在每一次的运行期期间转化为直接引用,这部分称为动态连接

        12、当一个方法被执行后,有两种方式退出这个方法。第一种方式是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调用当前方法的的方法称为调用者),是否有返回值和返回值的类型将根据遇到何种方法返回指令来决定,这种退出方法方式称为正常完成出口(Normal Method Invocation Completion)。另外一种退出方式是,在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,无论是Java虚拟机内部产生的异常,还是代码中使用athrow字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方式称为异常完成出口(Abrupt Method Invocation Completion)。一个方法使用异常完成出口的方式退出,是不会给它的调用都产生任何返回值的。     无论采用何种方式退出,在方法退出之前,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态。一般来说,方法正常退出时,调用者PC计数器的值就可以作为返回地址,栈帧中很可能会保存这个计数器值。而方法异常退出时,返回地址是要通过异常处理器来确定的,栈帧中一般不会保存这部分信息。 方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用都栈帧的操作数栈中,调用PC计数器的值以指向方法调用指令后面的一条指令等

· 本地方法栈

        1、本地方法本质上时依赖于实现的,虚拟机实现的设计者们可以自由地决定使用怎样的机制来让Java程序调用本地方法

        2、任何本地方法接口都会使用某种本地方法栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法

        3、很可能本地方法接口需要回调Java虚拟机中的Java方法,在这种情况下,该线程会保存本地方法栈的状态并进入到另一个Java栈

        4、如下图展示了JAVA虚拟机内部线程运行的全景图。一个线程可能在整个生命周期中都执行Java方法,操作它的Java栈;或者它可能毫无障碍地在Java栈和本地方法栈之间跳转

·  堆(划重点)

        1、堆的内存结构如图:

        2、堆内存分为年轻代(Young Generation)、老年代(Old Generation)

        3、年轻代又分为Eden和Survivor区。Survivor区由FromSpace和ToSpace组成。Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1

        4、堆内存用途:存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收

        5、JDK1.8版本废弃了永久代,替代的是元空间(MetaSpace),元空间与永久代上类似,都是方法区的实现,他们最大区别是:元空间并不在JVM中,而是使用本地内存

        6、元空间有注意有两个参数:

MetaspaceSize :初始化元空间大小,控制发生GC阈值

MaxMetaspaceSize : 限制元空间大小上限,防止异常占用过多物理内存

        7、移除永久代原因:为融合HotSpot JVM与JRockit VM(新JVM技术)而做出的改变,因为JRockit没有永久代。

有了元空间就不再会出现永久代OOM问题了

        8、各代关系:

新生成的对象首先放到年轻代Eden区,当Eden空间满了,触发Minor GC,存活下来的对象移动到Survivor0区,Survivor0区满后触发执行Minor GC,Survivor0区存活对象移动到Suvivor1区,这样保证了一段时间内总有一个survivor区为空。经过多次Minor GC仍然存活的对象移动到老年代。

老年代存储长期存活的对象,占满时会触发Major GC=Full GC,GC期间会停止所有线程等待GC完成,所以对响应要求高的应用尽量减少发生Major GC,避免响应超时。

Minor GC : 清理年轻代

Major GC : 清理老年代

Full GC : 清理整个堆空间,包括年轻代和永久代

所有GC都会停止应用所有线程

        9、QA

为什么survivor分为两块相等大小的幸存空间?

主要为了解决碎片化。如果内存碎片化严重,也就是两个对象占用不连续的内存,已有的连续内存不够新对象存放,就会触发GC

为什么会堆内存溢出?

在年轻代中经过GC后还存活的对象会被复制到老年代中。当老年代空间不足时,JVM会对老年代进行完全的垃圾回收(Full GC)。如果GC后,还是无法存放从Survivor区复制过来的对象,就会出现OOM(Out of Memory)

OOM常见原因分析

老年代内存不足:java.lang.OutOfMemoryError:Javaheapspace

解决办法:java 堆内存溢出, 此种情况最常见, 一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露, 需要通过内存监控软件查找程序中的泄露代码, 而堆大小可以通过虚拟机参数 - Xms,-Xmx 等修改

永久代内存不足:java.lang.OutOfMemoryError:PermGenspac

解决办法:java 永久代溢出, 即方法区溢出了, 一般出现于大量 Class 或者 jsp 页面, 或者采用 cglib 等反射机制的情况, 因为上述情况会产生大量的 Class 信息存储于方法区。当出现此种情况时可以通过更改方法区的大小来解决, 使用类似 - XX:PermSize=64m -XX:MaxPermSize=256m 的形式修改。注意, 过多的常量尤其是字符串也会导致方法区溢出

java.lang.StackOverflowError
   解决方法: JAVA 虚拟机栈溢出, 一般是由于程序中存在死循环或者深度递归调用造成的, 栈大小设置太小也会出现此种溢出。可以通过虚拟机参数 - Xss 来设置栈的大小

重点来了
(1)、Java heap space报错的原因及如何解救:

        (1.1)、请求创建一个超大对象,通常是一个大数组,举例子:从文件或者db中读取了100w条数据,申明了一个List或者Map,一条数据的大小哪怕1kb大小,这100w数据就要占用1Gb内存

        这里给个样例代码,后面不会再上复现代码了,各位自己下去动手去验证:

package com.feixiang.platform.stu.jvm.oom.stack;import com.feixiang.platform.stu.jvm.reference.strong.User;import java.util.ArrayList;
import java.util.List;/*** Created with IntelliJ IDEA.* Description: 创造一个OOM来实验:* 一定要够大的数组对象* 运行参数一定要修改,不然无法如愿** @PackageName com.feixiang.platform.stu.jvm.oom.stack* @Author: ldwtxwhspring* @Date: 2023-12-02 下午6:01* @Version: 1.0.0*/
public class StackHeapOomExample {public static void main(String[] args) {List<User> userList = new ArrayList<>();for(int i=0;i<1000000;i++){User user = new User();user.setId(i);user.setName("feixiang_"+i);user.setAddress("xxxx省—xxx市-xxx路-xxx小区-xxx楼"+i+"号房间");user.setMobile("133xxxx5680");userList.add(user);}}
}

运行参数修改如图:

 

运行结果如图:

 

        (1.2)、超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值。例如:双十一几万件商品快速被推向订单池,连续操作有不断锁库存加事务完整性逻辑,这些内存肯定不会被回收,而且会存在于完整的订单周期内。

        (1.3)、过度使用(Finalizer),该对象没有立即被 GC

        (1.4)、内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收,例如:读写文件完成没有刷新流或者没有关闭管道。

解决方法:

        针对大部分情况,通常只需要通过 -Xmx 参数调高 JVM 堆内存空间即可。如果仍然没有解决,可以参考以下情况做进一步处理:

        

  • 如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。
  • 如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级。
  • 如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接。
  • 对于外部网络请求,可以设置超时时间,请求回调改造
(2)、PermGen space报错原因分析及解救:

       (2.1)、 该错误表示永久代 (Permanent Generation) 已用满, 通常是因为加载的 class 数目太多或体积太大

        (2.2)、原因分析,永久代存储对象主要包括以下几类:        

  • 加载/缓存到内存中的 class 定义,包括类的名称,字段,方法和字节码;
  • 常量池;
  • 对象数组/类型数组所关联的 class;
  • JIT 编译器优化后的 class 信息。
  • PermGen 的使用量与加载到内存的 class 的数量/大小正相关。

      (2.2)、解决方案,根据 Permgen space 报错的时机,可以采用不同的解决方案,如下所示:

  • 程序启动报错,修改 -XX:MaxPermSize 启动参数,调大永久代空间。
  • 应用重新部署时报错,很可能是没有应用没有重启,导致加载了多份 class 信息,只需重启 JVM 即可解决。
  • 运行时报错,应用程序可能会动态创建大量 class,而这些 class 的生命周期很短暂,但是 JVM 默认不会卸载 class,可以设置 -XX:+CMSClassUnloadingEnabled 和 -XX:+UseConcMarkSweepGC这两个参数允许 JVM 卸载 class。
  • 如果上述方法无法解决,可以通过 jmap 命令 dump 内存对象 jmap-dump:format=b,file=dump.hprof ,然后利用 Eclipse MAT Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation 功能逐一分析开销最大的 classloader 和重复 class
(3)、java.lang.OutOfMemoryError:GC overhead limit exceeded 错误原因及解决:

当 Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次,就会抛出 java.lang.OutOfMemoryError:GC overhead limit exceeded 错误。简单地说,就是应用程序已经基本耗尽了所有可用内存, GC 也无法回收。

此类问题的原因与解决方案跟 Javaheap space 非常类似,请回看上文

(4)、Metaspace错误原因及解救:

JDK 1.8 使用 Metaspace 替换了永久代(Permanent Generation),该错误表示 Metaspace 已被用满,通常是因为加载的 class 数目太多或体积太大。

此类问题的原因与解决方法跟 Permgenspace 非常类似,可以参考上文。需要特别注意的是调整 Metaspace 空间大小的启动参数为 -XX:MaxMetaspaceSize。

(5)、Unable to create new native thread错误原因及解救:

        (5.1)、每个 Java 线程都需要占用一定的内存空间,当 JVM 向底层操作系统请求创建一个新的 native 线程时,如果没有足够的资源分配就会报此类错误。

        (5.2)、原因分析,JVM 向 OS 请求创建 native 线程失败,就会抛出 Unableto createnewnativethread,常见的原因包括以下几类:

  • 线程数超过操作系统最大线程数 ulimit 限制;
  • 线程数超过 kernel.pid_max(只能重启);
  • native 内存不足;

        (5.3)、该问题发生的常见过程主要包括以下几步:

  • JVM 内部的应用程序请求创建一个新的 Java 线程;
  • JVM native 方法代理了该次请求,并向操作系统请求创建一个 native 线程;
  • 操作系统尝试创建一个新的 native 线程,并为其分配内存;
  • 如果操作系统的虚拟内存已耗尽,或是受到 32 位进程的地址空间限制,操作系统就会拒绝本次 native 内存分配;
  • JVM 将抛出 java.lang.OutOfMemoryError:Unableto createnewnativethread 错误。

        (5.4)、解决方案

  • 升级配置,为机器提供更多的内存;
  • 降低 Java Heap Space 大小;
  • 修复应用程序的线程泄漏问题;
  • 限制线程池大小;
  • 使用 -Xss 参数减少线程栈的大小;
  • 调高 OS 层面的线程最大数:执行 ulimia-a 查看最大线程数限制,使用 ulimit-u xxx 调整最大线程数限制ulimit -a … 省略部分内容 … max user processes (-u) 16384
(6)、Out of swap space原因分析及解救:

        (6.1)、该错误表示所有可用的虚拟内存已被耗尽。虚拟内存(Virtual Memory)由物理内存(Physical Memory)和交换空间(Swap Space)两部分组成。当运行时程序请求的虚拟内存溢出时就会报 Outof swap space? 错误。

        (6.2)、原因分析,该错误出现的常见原因包括以下几类:

  • 地址空间不足;
  • 物理内存已耗光;
  • 应用程序的本地内存泄漏(native leak),例如不断申请本地内存,却不释放。
  • 执行 jmap-histo:live 命令,强制执行 Full GC;如果几次执行后内存明显下降,则基本确认为 Direct ByteBuffer 问题。

        (6.3)、解决方案,根据错误原因可以采取如下解决方案:

  • 升级地址空间为 64 bit;
  • 使用 Arthas 检查是否为 Inflater/Deflater 解压缩问题,如果是,则显式调用 end 方法。
  • Direct ByteBuffer 问题可以通过启动参数 -XX:MaxDirectMemorySize 调低阈值。
  • 升级服务器配置/隔离部署,避免争用。
(7)、Kill process or sacrifice child分析及解决:

        (7.1)、有一种内核作业(Kernel Job)名为 Out of Memory Killer,它会在可用内存极低的情况下“杀死”(kill)某些进程。OOM Killer 会对所有进程进行打分,然后将评分较低的进程“杀死”,具体的评分规则可以参考 Surviving the Linux OOM Killer。不同于其他的 OOM 错误, Killprocessorsacrifice child 错误不是由 JVM 层面触发的,而是由操作系统层面触发的。

        (7.2)、原因分析

默认情况下,Linux 内核允许进程申请的内存总量大于系统可用内存,通过这种“错峰复用”的方式可以更有效的利用系统资源。

然而,这种方式也会无可避免地带来一定的“超卖”风险。例如某些进程持续占用系统内存,然后导致其他进程没有可用内存。此时,系统将自动激活 OOM Killer,寻找评分低的进程,并将其“杀死”,释放内存资源。

        (7.3)、解决方案

  • 升级服务器配置/隔离部署,避免争用。
  • OOM Killer 调优。
(8)、Direct buffer memory原因及解救:

        (8.1)、java 允许应用程序通过 Direct ByteBuffer 直接访问堆外内存,许多高性能程序通过 Direct ByteBuffer 结合内存映射文件(Memory Mapped File)实现高速 IO。

        (8.2)、原因分析

  • Direct ByteBuffer 的默认大小为 64 MB,一旦使用超出限制,就会抛出 Directbuffer memory 错误。

        (8.3)、解决方案

  • Java 只能通过 ByteBuffer.allocateDirect 方法使用 Direct ByteBuffer,因此,可以通过 Arthas 等在线诊断工具拦截该方法进行排查。
  • 检查是否直接或间接使用了 NIO,如 netty,jetty 等。
  • 通过启动参数 -XX:MaxDirectMemorySize 调整 Direct ByteBuffer 的上限值。
  • 检查 JVM 参数是否有 -XX:+DisableExplicitGC 选项,如果有就去掉,因为该参数会使 System.gc() 失效。
  • 检查堆外内存使用代码,确认是否存在内存泄漏;或者通过反射调用 sun.misc.Cleaner 的 clean() 方法来主动释放被 Direct ByteBuffer 持有的内存空间。
  • 内存容量确实不足,升级配置。
· 程序计数器

        1、线程私有

        2、每个线程一块内存,指向当前正在执行的字节码的行号。如果当前线程是native方法,则其值为null

        3、如果执行的是java方法,那么记录的是正在执行的虚拟机字节码指令的地址的地址,如果是native方法,计数器的值为空(undefined)

        4、这块内存区域是虚拟机规范中唯一没有OutOfMemoryError的区域

二、本地内存

· 元数据区

1、主要用来保存被虚拟机加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据

2、存在OOM的区:一个元数据区的大小决定了Java虚拟机可以装载的类的多少

3、包括final修饰的变量、字面量、类和接口全限定名、字段、方法名称以及修饰符等永恒不变的东西

4、并不是所有的字面量都会存储在类文件常量池中,比如对于方法内(注意是方法)整数字面量,如果值在-32768~32767之间则会被直接嵌入JVM指令中去,不会保存在常量池中

· 直接内存

1、java通过native方法去调用

2、在调用这种native方法的时候,就会有线程对应的本地方法栈,这个其实类似于java虚拟机栈。也是存放各种native方法的局部变量表之类的信息

3、还有一块区域,不是jvm的,通过NIO中的allocateDirect这种API,可以在jvm堆外分配内存空间,然后通过java虚拟机栈里的DirectByteBuffer来引用和操作堆外内存空间

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

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

相关文章

安装mysql数据库

1.1下载APT存储库&#xff08;下载链接&#xff09; 1.2安装APT存储库&#xff08;注意好正确的路径&#xff09; 将下载的文件传输到linux服务器对应目录下后执行以下命令&#xff1a; sudo dpkg -i mysql-apt-config_0.8.10-1_all.deb 选择mysql5.7 然后点击ok 然后执行 s…

应用架构——集群、分布式、微服务的概念及异同

一、什么是集群&#xff1f; 集群是指将多台服务器集中在一起&#xff0c; 每台服务器都实现相同的业务&#xff0c;做相同的事&#xff1b;但是每台服务器并不是缺 一不可&#xff0c;存在的主要作用是缓解并发能力和单点故障转移问题。 集群主要具有以下特征&#xff1a; …

JAVA使用POI向doc加入图片

JAVA使用POI向doc加入图片 前言 刚来一个需求需要导出一个word文档&#xff0c;文档内是系统某个界面的各种数据图表&#xff0c;以图片的方式插入后导出。一番查阅资料于是乎着手开始编写简化demo,有关参考poi的文档查阅 Apache POI Word(docx) 入门示例教程 网上大多数是XXX…

el-table-column 添加 class类

正常添加class 发现没有效果 class"customClass" 发现并没有添加上去 看了一下官网发现 class-name 可以实现 第一步: :class-name"customClass" 第二步 : customClass: custom-column-class, 然后就发现可以了

Qt简介、工程文件分离、创建Qt工程、Qt的帮助文档

QT 简介 core&#xff1a;核心模块&#xff0c;非图形的接口类&#xff0c;为其它模块提供支持 gui&#xff1a;图形用户接口&#xff0c;qt5之前 widgets&#xff1a;图形界面相关的类模块 qt5之后的 database&#xff1a;数据库模块 network&#xff1a;网络模块 QT 特性 开…

IntelliJ IDEA使用Eval Reset

文章目录 IntelliJ IDEA使用Eval Reset说明具体操作 IntelliJ IDEA使用Eval Reset 说明 操作系统&#xff1a;windows10 版本&#xff1a;2020.1 IntelliJ IDEA安装可查看&#xff1a;安装教程 具体操作 添加&#xff0c;输入网址 https://plugins.zhile.io然后搜索“IDE E…

IntelliJ IDEA安装

文章目录 IntelliJ IDEA安装说明下载执行安装 IntelliJ IDEA安装 说明 操作系统&#xff1a;windows10 版本&#xff1a;2020.1 下载 官网地址 执行安装

奇点云2023数智科技大会来了,“双12”直播见!

企业数字化进程深入的同时&#xff0c;也在越来越多的新问题中“越陷越深”&#xff1a; 数据暴涨&#xff0c;作业量和分析维度不同以往&#xff0c;即便加了机器&#xff0c;仍然一查就崩&#xff1b; 终于搞定新增渠道数据的OneID融合&#xff0c;又出现几个渠道要变更&…

自动定量包装机市场研究: 2023年行业发展潜力分析

中国包装机械业取得了快速发展&#xff0c;但也出现了一些低水平重复建设现象。据有关资料显示&#xff0c;与工业发达国家相比&#xff0c;中国食品和包装机械产品品种缺乏25%-30%&#xff0c;技术水平落后15-25年。我国包装专用设备制造行业规模以上企业有319家&#xff0c;主…

Vue3实现一个拾色器功能

​ <template><div class"color"><button v-if"hasEyeDrop" click"nativePick">点击取色</button><input v-else type"color" input"nativePick" v-model"selectedColor" /><p&…

Markdown从入门到精通

Markdown从入门到精通 文章目录 Markdown从入门到精通前言一、Markdown是什么二、Markdown优点三、Markdown的基本语法3.1 标题3.2 字体3.3 换行3.4 引用3.5 链接3.6 图片3.7 列表3.8 分割线3.9 删除线3.10 下划线3.11 代码块3.12 表格3.13 脚注3.14 特殊符号 四、Markdown的高…

2024黑龙江省职业院校技能大赛信息安全管理与评估样题第二三阶段

2024黑龙江省职业院校技能大赛暨国赛选拔赛 "信息安全管理与评估"样题 *第二阶段竞赛项目试题* 本文件为信息安全管理与评估项目竞赛-第二阶段试题&#xff0c;第二阶段内容包括&#xff1a;网络安全事件响应、数字取证调查和应用程序安全。 极安云科专注技能竞赛…

openharmony 开发环境搭建和系统应用编译傻瓜教程

一、DevEco Studio 安装 当前下载版本有两个&#xff0c;由于低版本配置会有各种问题&#xff0c;我选择高版本安装 低版本下载链接 HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 高版本下载链接 OpenAtom OpenHarmony 解压后安装 双击安装 安装配置 二、创建测…

IntelliJ IDEA的下载安装配置步骤详解

引言 IntelliJ IDEA 是一款功能强大的集成开发环境&#xff0c;它具有许多优势&#xff0c;适用于各种开发过程。本文将介绍 IDEA 的主要优势&#xff0c;并提供详细的安装配置步骤。 介绍 IntelliJ IDEA&#xff08;以下简称 IDEA&#xff09;之所以被广泛使用&#xff0c;…

docker镜像仓库hub.docker.com无法访问

docker镜像仓库hub.docker.com无法访问 文章主要内容&#xff1a; 介绍dockerhub为什么无法访问解决办法 1 介绍dockerhub为什么无法访问 最近许多群友都询问为什么无法访问Docker镜像仓库&#xff0c;于是我也尝试去访问&#xff0c;结果果然无法访问。 大家的第一反应就是…

数组循环:使用 for-of 循环

首先我们先创建一个数组&#xff0c;从之前的对象中取得 const menu [...restaurant.starterMenu,...restaurant.mainMenu];在之前&#xff0c;我们如果想要打印数组中的每一个数据&#xff0c;我们通常会写for循环来一个一个打印出来&#xff0c;现在我们可以使用for-of循环…

Elasticsearch:什么是检索增强生成 (RAG)?

检索增强生成 (RAG) 定义 检索增强生成 (RAG) 是一种利用来自私有或专有数据源的信息来补充文本生成的技术。 它将旨在搜索大型数据集或知识库的检索模型与大型语言模型 (LLM) 等生成模型相结合&#xff0c;后者获取该信息并生成可读的文本响应。 检索增强生成可以通过添加来…

在线客服系统有哪些接入方式?

在线客服系统在当今的商业环境中还是非常重要的角色的。它通过提供实时又个性化的客户服务&#xff0c;让客户满意的同时还能提高转化率&#xff0c;更能维护品牌形象。然而企业在选择在线客服系统时必须了解不同的接入方式&#xff0c;以便选择最适合自己的方式。下面我以合从…

消费升级:无人零售的崛起与优势

消费升级&#xff1a;无人零售的崛起与优势 随着人们生活水平的提高&#xff0c;消费内容正在从生存型消费转向以精神体验和享乐为主的发展型消费。社会居民的消费结构不断变迁&#xff0c;明显呈现消费升级趋势。个性化和多元化消费势头正在崛起&#xff0c;特别是无人零售的自…

【教学类-35-02】20231207大班姓名描字帖:A4单面3*10个姓名,双面共60个名字

背景需求&#xff1a; 需求1——需要字帖 大4班班主任说&#xff1a;你能给我们班孩子做一套写名字的字帖吗&#xff1f;我想让他们练习写名字。 我说&#xff1a;没问题。我找找已经有的样式给你看看&#xff0c;再打印。 打开电脑&#xff0c;我把曾经做的一套“大字贴”…