JVM理论(六)执行引擎--垃圾回收

概述

  • 垃圾: 指的是在运行程序中没有任何指针指向的对象
  • 垃圾回收目的: 为了及时清理空间使得程序可以正常运行
  • 垃圾回收机制: JVM采取的是自动内存管理,即JVM负责对象的创建以及回收,将程序员从繁重的内存管理释放出来,更加专注业务的开发
  • 垃圾回收区域: 频繁收集Young区(新生代),较少收集Old区(老年代),基本不动永久代/元空间
  • 垃圾回收算法
    • 标记阶段
      • 引用计数算法
      • 可达性分析算法
    • 清除阶段
      • 标记-清除算法
      • 复制算法
      • 标记压缩算法
    • 分代收集算法
    • 增量收集算法
    • 分区算法
  • 垃圾回收finalization机制

    • java提供了对象终止(finalization)机制允许开发人员提供对象被销毁前的自定义处理逻辑
    • 当垃圾对象被回收之前一定会调用finalize()方法
    • 不要主动调用对象的finalize方法,交由垃圾回收机制执行,原因如下
      • 极端情况下,若没发生GC,则finalize将不会执行
      • finalize方法中可以使得对象复活
      • finalize方法影响GC性能
    • 由于finalize方法的存在,JVM中的对象一般处于三种可能的状态,且只有不可触及的对象才会被垃圾回收
      • 可触及的: 从根节点开始,可以到达这个对象
      • 可复活的: 对象的引用都被释放,但有可能在finalize方法中复活
      • 不可触及的: 对象没有在finalize方法中复活,即进入不可触及状态,不可触及状态的对象不可能被复活,因为finalize方法只会被调用一次
  • System.gc:会显示触发Full GC,但无法保证垃圾收集器实时调用,开发人员一般不会主动调用
  • 内存溢出: 没有可用的内存,并且垃圾收集器无法提供更多的内存(即无法有效回收内存空间),没有空闲的内存情况原因如下
    • Java虚拟机堆内存设置不足(可通过-Xms、-Xmx来调整)
    • 代码中创建了大量大对象,并且长时间无法被垃圾收集器收集
  • 内存泄漏:对象不会被程序用到了,但GC又不能进行回收;内存泄漏不会立刻引起程序崩溃,但它会逐渐蚕食内存空间,直至内存耗尽,最终出现OOM;常见内存泄漏情况
    • 单例模式: 单例生命周期和应用程序一样长,若单例程序持有对外部对象的引用,那该外部对象在程序正常运行过程中永远也不会被回收
    • 一些提供close的资源未关闭:数据连接,网络连接和io连接以及报表workbook对象必须手动close,否则不会被回收
  • STW:stop the world,指的是GC事件发生过程中应用程序会产生停顿(任何GC都会产生STW),且停顿产生时整个应用程序线程都会被暂停,GC完成后会恢复应用程序,频繁中断会让用户体验不好,所以我们需要尽可能缩短STW的时间
  • 并发和并行对比
    • 并发:多个事件在同一时间段内发生(CPU时间片段极速切换);并发的多个任务之间是互相抢占资源的
    • 并行:多个事件在同一时间点同时发生;并行的多个任务不会互相抢占资源
    • 只有在多CPU或者一个CPU多核情况下才会发生并行,否则看似同时发生的事情都是并发执行的
  • 安全点:程序在运行时并非在所有地方都能停顿下来进行GC,只有在特定位置才可以,这些位置称为安全点(safe point),若安全点过少可能导致GC等待时间太长,过多可能导致性能降低,所以我们通常选择一些执行时间较长的指令作为安全点,比如方法调用、循环跳转、异常跳转等
    • 安全区域:在一段代码片段中,对象的引用关系不会发生变化,在这个区域中的任何位置开始GC都是安全的,也可以看做被扩展的安全点
  • java中四种对象引用
    • 强引用、软引用、弱引用、虚引用共4种引用,强度依次逐渐减弱;除了强引用,其他3种引用类均包含在java.lang.ref包下
      • 引用(StrongReference): 程序中普遍存在的引用关系(程序中99%都是强引用),如Object obj = new Object(),只要引用关系存在,垃圾收集器永远不会回收掉,强引用是造成内存溢出的主要原因
      • 引用(SoftReference): 内存不足即回收,在JVM内存不足时,进行垃圾回收时才进行二次回收(一次回收是针对不可达对象);主要用于高速缓存场景
      • 引用(WeakReference): 发现即回收,无论JVM内存是否充足,在进行垃圾回收时对只被弱引用关联的对象进行回收
      • 引用(PhantomReference): 对象回收跟踪,对象是是否有虚引用对其生命时间无任何影响,虚引用的目的就是在该对象被回收时发出系统通知,即跟踪垃圾回收过程

垃圾回收算法

标记阶段-引用计数算法(Python采用的算法,Java未使用)

引用计数算法比较简单,通过对每个对象保存一个整型的引用计数器属性,用于记录对象被引用的情况,比如对于一个对象A,只要有一个对象引用A,则A的引用计数器就加1,当引用失效时就减1,当对象A的引用计数器值为0,即表示对象A不可能再被使用,可进行回收

  • 优点
    • 实现简单,垃圾对象便于辨识
    • 判定效率较高,回收没有延迟性
  • 缺点:
    • 需要单独存储计数器,增加了存储空间的开销
    • 每次赋值需要更新计数器,增加了时间开销
    • 最严重的是无法处理循环引用的情况(导致Java垃圾回收器没有使用该算法)
      • 扩展: 人工智能中Python则使用该算法进行垃圾回收,它解决循环引用问题的策略
        • 手动解除,在合适时机解除引用关系
        • 使用弱引用,weakref是python提供的标准库,旨在解决循环引用

标记阶段-可达性分析算法/根搜索算法/追踪性垃圾收集(Java采用))

可达性分析算法是以根对象集合GC Roots为起点,按照从上至下的方式搜索被根对象集合中所连接的对象是否可达;如果该对象没有任何引用链相连,则是不可达,意味着该对象已经死亡可以标记为垃圾对象;可达性分析算法有效的解决在引用计数算法中循环引用的问题,防止内存泄漏的发生.
GC Roots包括的类或者对象

  • 虚拟机栈中引用的对象:各个方法中使用到的参数、局部变量(即栈帧中局部变量表中的引用对象)
  • 本地方法栈引用的对象
  • 方法区中类静态属性引用的对象: java类静态变量
  • 方法区中常量引用的对象: 字符串常量池的里的引用
  • 同步锁synchronized持有的对象

清除阶段-标记-清除(Mark-Sweep)算法

当堆中有效空间被耗尽的时候,就会停止用户线程(STW),然后进行标记和清除操作;

  • 标记:垃圾回收器Collector从GC Root开始遍历,标记所有被引用的对象,一般会在对象头中记录为可达对象
  • 清除:垃圾回收器Collector对堆内存从头到尾进行线性遍历,如果发现某个对象在它的对象头中没有标记为可达对象,则将其视为垃圾进行回收(注意:清除并非真的置空,而是把需要清除的对象地址保存在空闲地址列表中,下次有新对象需要存储时,会判断该垃圾所在的内存位置是否能够存储,若能则覆盖原有垃圾)

缺点

  • 效率不算高
  • 进行GC需要停止整个应用程序,导致用户体验差
  • 空闲内存不连续会产生内存碎片,需要JVM维护一个空闲列表

清除阶段-复制(Copy)算法

该算法核心思想是将可用的内存空间分为两块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存角色,最后完成垃圾回收(复制算法适用于复制没有存在很多存活的对象,即新生代)

优点

  • 没有标记和清除过程,实现简单,运行高效
  • 复制以后保证空间的连续性,不会出现“碎片”问题

缺点

  • 需要两倍的内存空间

清除阶段-标记-压缩(Mark-Compact)算法

由于标记清除算法会产生碎片化,所以设计者在此基础上进行了改进诞生了标记压缩算法,所以标记压缩算法最终效果=标记-清除算法+内存碎片整理,即标记压缩算法也可以称为标记-清除-压缩算法

标记压缩过程

  • 标记阶段和标记清除算法一样,从根节点开始标记所有被引用的对象
  • 压缩/整理:将所有存活的对象压缩到内存的一端,按顺序排列存储
  • 最后清理边界外所有内存空间

优点

  • 消除了标记-清除算法中内存区域碎片化的缺点,我们给新对象分配内存空间时,JVM只需要持有一个内存起始地址即可
  • 消除了复制算法中内存减半的高额代价

缺点

  • 效率上标记-压缩算法低于复制算法
  • 压缩/整理过程中,若对象被其他对象引用,则还需要调整引用的地址
  • 需要全称暂停用户应用你程序,即STW

三种垃圾清除算法对比

分代收集算法(CMS垃圾回收器)

由于不同的对象生命周期是不一样的,因此不同生命周期的对象可以采取不同的收集方式,以便提高回收效率;目前几乎所有的GC都是采用分代收集算法执行垃圾回收的,Hotspot中基于分代概念,对于新生代和老年代各自特点就采用了不同的算法

  • 新生代:对象生命周期短,存活率低,回收频繁;采用复制算法回收效率最高,因为复制算法只和当前存活对象多少有关,且对于内存利用率不高的问题,hotspot也通过survivor区域进行缓解
  • 老年代:对象生命周期长,存活率高,回收不及新生代频繁;一般采用标记-清除或者标记-压缩和标记-清除算法混合实现

分代收集案例

以hotspot中CMS垃圾回收器为例,CMS是基于Mark-Sweep算法实现,对于对象的回收效率很高.而对于碎片问题,CMS又采用了基于Mark-Compact算法的Serial old回收器作为补偿措施(当内存回收不佳时利用Serial old执行Full GC进行垃圾回收)

增量收集算法

基本思想

如果一次性将所有垃圾进行处理,需要造成系统长时间停顿,极大影响用户体验;因此我们可以让垃圾收集线程和应用程序线程交替执行,每次垃圾收集线程只收集一小片区域内存空间,接着切换到应用程序线程.依次反复执行知道垃圾收集完成。增量收集算法基础仍是标记清除和复制算法,它对线程间冲突进行了妥善处理,允许垃圾收集线程以分阶段的方式完成标记-清除和复制工作.

分区算法(G1垃圾回收器)

为了更好的控制GC产生的停顿时间,分区思想是将一块大的内存区域分割成多个小块,根据目标停顿时间,每次合理的回收若干个小区间region,而不是整个堆空间,从而减少一次GC所产生的STW
分代算法思想是按照对象生命周期长短划分成两个部分;而分区算法思想是将整个堆空间划分成连续不同的region;其中每个region独立使用,独立回收,这种方式可以控制一次回收一定数量的region,已达到更好的控制GC产生的停顿时间

垃圾回收器

GC核心性能指标

  • 吞吐量:运行用户线程执行的时间占总运行时间的比例(总运行时间=用户线程执行时间+GC时间);适用于服务器端程序
  • 暂停时间STW:执行垃圾回收时用户线程暂停的时间,即延迟时长;适用于交互式程序,如web应用

GC垃圾回收器的目标就是在保证最大吞吐量的情况下,最大化的降低STW

 GC分类

  • 按垃圾回收线程分类
    • 串行垃圾回收器(同一时间段只允许一个CPU用于执行垃圾回收操作)
    • 并行垃圾回收器(同一时间段允许多个CPU(或者单CPU多核)用于执行垃圾回收操作)
  • 按工作模式分类
    • 并发式垃圾回收器:垃圾回收线程和用户线程并发交替执行,减少STW
    • 独占式垃圾回收器:只允许垃圾回收线程运行,停止所有用户线程直到垃圾回收结束
  • 按工作内存区间
    • 年轻代垃圾回收器和老年代垃圾回收器

垃圾回收器和JVM有紧密的联系,不同的JVM之间的GC有一定的区别,基于hotspot虚拟机有7种经典的垃圾收集器

  • 串行GC: Serial、Serial Old
  • 并行GC: ParaNew、Parallel Scavenge、Parallel Old
  • 并发GC: CMS、G1

GC组合关系

  • 其中serial old作为CMS出现“Concurrent Mode Failure”的后备方案(即会执行FGC回收可用内存空间)
  • 红色虚线:JDK8/JDK9后废弃/移除了serial GC搭配CMS GC以及ParaNew 搭配Serial old使用
  • 绿色虚线:JDK14弃用Parallel Scavenge GC搭配SerialOld GC,以及移除了CMS回收器

由于Java使用场景很多,所以需要针对不同场景提供不同的垃圾回收器以实现更高垃圾收集的性能

垃圾回收器说明

Serial 回收器(串行回收)

  • Serial 收集器是最基本、历史最悠久的垃圾收集器,简单高效
  • hotspot中client模式(32位操作系统)下的默认新生代垃圾收集器
  • 采用复制算法,串行回收以及采用STW机制方式执行内存回收
  • Serial old收集器也采用了串行回收和STW,不过采用的是标记-压缩算法
  • Serial old是client模式(32位操作系统)下的默认老年代垃圾收集器
  • Serial old是server模式(64位操作系统)下的用途
    • 与新生代的parallel scavenge配合使用
    • 作为老年代CMS的后备垃圾收集方案
  • -XX:+UserSerialGC 指定年轻代和老年代都使用串行收集器,即新生代使用Serial GC,老年代使用Serial Old GC

ParaNew回收器(并行回收)

  • Serial GC是以单线程方式回收新生代,而ParaNew则是它的多线程版本,且只能回收新生代
  • 同样采用复制算法和STW机制
  • 很多JVM运行在Server模式下新生代默认垃圾回收器
  • ParaNew收集器适合多CPU环境,可以更快速完成垃圾收集提升程序的吞吐量

  • -XX:+UserParaNewGC 指定年轻代采用的收集器,即新生代使用Serial GC,不影响老年代

Parallel回收器(并行回收且追求高吞吐量)

  • Parallel Scavenge回收器(并行回收且更追求吞吐量)
  • Parallel Scavenge也属于并行回收年轻代的方式
  • 同样采用复制算法和STW机制
  • Parallel Scavenge相比ParaNew是一种吞吐量优先的GC
  • 更适合后台运算而不需要太多交互的任务,常用与服务器环境
  • Parallel Old代替了Serial old采用并行方式回收老年代
  • Parallel Old采用了标记-压缩算法
  • Parallel Old同样采用复制算法和STW机制
  • -XX:+UserParallelGC 指定年轻代采用的并行收集器
    -XX:+UserParallelOldGC 指定老年代采用的收集器,jdk8中默认的回收器,与年轻代设置其中一个即可,会互相激活

CMS回收器(追求低延迟)

  • jdk5版本中hotspot推出了强交互应用场景下的划时代的垃圾回收器,实现了垃圾线程和用户线程同时工作
  • 尽可能缩短垃圾收集时的STW
  • 采用标记-清除算法,也存在STW
  • 由于Parallel Scavenge无法和CMS配合使用(底层框架不同),所以后来推出了ParaNew适配CMS

CMS工作原理

CMS执行流程主要包含4个过程,初始标记、并发标记、重新标记、并发清理(其中只有初始标记和重新标记存在STW)

  • 初始标记:也称为initial-mark,该阶段会STW,且仅仅是标记GC Roots能直接关联到的对象,标记完成则恢复之前被暂停的所有用户线程,由于直接关联对象比较小,所以该阶段标记速度很快
  • 并发标记:通过初始标记的对象开始遍历整个对象图的过程,该阶段耗时长但不需要停顿用户线程,可以并发执行用户线程和垃圾回收线程
  • 重新标记:由于并发标记阶段中用户线程和垃圾线程同时执行,可能存在一些标记的对象产生变动,所以需要进行修正,该阶段时长比初始时间长但远远小于并发标记时长
  • 并发清理:清理删除掉标记阶段判断的已经死亡的对象,释放内存空间.由于采用的标记-清除算法不涉及移动内存空间,所以该阶段可以和用户线程并发执行

优点

  • 并发收集
  • 低延迟(STW短)


缺点

  • 采用的标记-清除算法会产生内存碎片
  • 降低系统的吞吐量: 并发阶段垃圾线程会占用一定的资源,所以总的吞吐量会减少
  • CMS无法处理浮动垃圾: 并发阶段可能产生新的垃圾对象,CMS无法及时回收这些垃圾,只能在下一次GC时回收

注意

  • 由于在垃圾收集阶段用户线程没有中断,所以在CMS回收郭过程中,必须确保应用程序拥有足够的内存空间.因此当堆内存使用率达到某一阈值时,便开始进行回收,以确保在CMS期间依然有足够的内存空间支持程序运行;在CMS期间预留的内存无法满足应用程序需求时,就会出现“concurrent Mode failure"失败,这时虚拟机将启动后备预案,临时启用Serial old 收集器重新进行老年代的垃圾回收,此时STW耗时就比较长了
  • 由于采用标记-清除算法,所以内存会产生碎片化,在为新对象分配空间时将无法使用指针碰撞技术,而只能选择空闲列表执行内存的分配

G1回收器(区域分代化)

为了适应现在不断扩大的内存和不断增加的处理器数量,进一步降低暂停时间并且兼顾良好的吞吐量。官方给G1设定的目标就是在延迟可控的情况下获得尽可能高的吞吐量,称其为“全功能收集器”

  • G1是一个并行回收器,它把堆内存分割成代表Eden,Survivor,old的region
  • G1 GC避免在整个堆区进行垃圾收集,G1跟踪各个Region垃圾的价值(内存空间大小)以及回收所需的时间,在后台维护一个有限列表,每次根据允许的收集时间,优先回收价值最大的region
  • G1主要针对配备多核CPU及大容量内存的机器,兼具高吞吐量和低延迟
  • G1是JDK9以后的默认垃圾回收器,且CMS在JDK9中被标记为废弃(JDK14已移除)

优点

  • 并行与并发
    • 并行性:G1在回收期间,可以有多个GC线程同时工作,有效利用多核计算能力
    • 并发性:G1可以和用户线程交替工作
  • 分代收集:G1仍然区分年轻代和老年代,同时不要求它们都必须是连续等
  • 空间整合:将内存划分一个个region,内存回收以region为基本单位,region之间是复制算法,整体上采用标记-压缩算法,避免内存碎片化,对于大堆时G1优势更加明显
  • 可预测的停顿时间模型:由于分区以及每次根据允许的收集时间,优先回收价值最大的region,获取最高的收集效率

缺点

G1相比CMS,在用户程序运行过程中,需要占用额外执行负载(比如:G1需要通过记忆集Rset存储其他region的引用进而不必全堆扫描)

相比CMS,如下场景更适合G1

  • 超过50%的Java堆被活动数据占用
  • 对象分配频率或年代提升频率变化很大
  • GC停顿时间过长(0.5-1s)
  • 经验上来看,在6-8G之间,G1和CMS表现差不多,而小于此区间CMS更优秀,否则G1更优秀

常见问题

Serial GC、Parallel GC、CMS区别

  • 如果追求最小化使用内存和并行开销,选择Serial GC
  • 如果追求组嗲话应用程序的吞吐量,选择Parallel GC
  • 如果追求最小化的GC中断或停顿时间,请选择CMS GC

MinorGC、MajorGC、FullGC区别
JVM在进行GC时,并非每次都对新生代、老年代、方法区区域一起回收的,大部分时候回收都是指新生代,而针对Hotspot VM的实现,按照回收区域分为Partial GC部分收集和Full GC整堆回收;

  • 部分收集又分为新生代收集和老年代收集以及混合收集
    • 新生代收集:Minor GC/YGC,对新生代的Eden和S0以及S1的垃圾回收
    • 老年代收集:Major GC/Old GC,对老年代区域的垃圾回收,目前只有CMS GC会有单独收集老年代行为
    • 混合收集: Mixed GC,对新生代以及部分老年代垃圾收集,目前只有G1 GC会有这种方式
  • 整堆收集: Full GC,收集整个Java堆和方法区的垃圾收集,因为方法区几乎不执行GC,所以我们常常将Major GC和Full GC视为同一个含义

垃圾回收条件

  • 新生代收集触发条件
    • 当新生代中的Eden区域满的时候触发YGC
    • Survivor区不会触发GC;而且YGC非常频繁且速度很快
    • YGC会引发STW,直到垃圾回收完成用户线程才恢复运行
  • 老年代收集触发条件
    • 老年代空间不足时会发生Major GC
    • 通常在发生Major GC前会进行一次YGC
    • Major GC速度一般比YGC慢10倍以上,STW时间更长
  • 整堆收集触发条件
    • 调用System.gc(),系统建议执行Full GC,但不一定执行
    • 老年代空间不足
    • 通过YGC进入老年代的平均大小大于老年代的可用内存
    • Eden和S0存货对象复制到S1时,S1空间不能够存放该对象,则会把对象转存到老年代,且此时老年代可用内存大小小于该对象大小
    • 方法区空间不足

注意:我们开发中针对JVM调优,就是减少Full GC进而减少STW

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

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

相关文章

【面试】 redis击穿现象?如何防止击穿?

文章目录 背景击穿案例解决方案:通过synchronized双重检查机制:某个key只让一个线程查询,阻塞其它线程设置value永不过期(设置热点数据永不过期)使用互斥锁(mutex key) 背景 大家都知道,计算机的瓶颈之一就是IO,为了解决内存与磁…

【深度学习】yolov 图片训练的时候的遇到的warning: corrupt JPEG restored and saved

报错原因 是图片在dataset.py 走验证时报的错误。 if im.format.lower() in (jpg, jpeg):with open(im_file, rb) as f:f.seek(-2, 2)if f.read() ! b\xff\xd9: # corrupt JPEGImageOps.exif_transpose(Image.open(im_file)).save(im_file, JPEG, subsampling0, quality100)m…

数据结构——顺序表

即使你内心没有一尊明月,也要给自己留下一方皎洁 文章目录 什么是顺序表 顺序表的实现 顺序表内部基础设置 结构体数据类型重定义 顺序表结构定义 顺序表空间初始化及扩容设置 顺序表空间的初始化及销毁 顺序表的扩容 顺序表基本功能 尾插尾删 头插头删…

css设置八等分圆

现需要上图样式的布局,我通过两张向右方的图片,通过定位和旋转完成了布局。 问题: 由于是通过旋转获取到的样式,实际的盒子是一个长方形,当鼠标移入对应的箭头时选中的可能是其他盒子,如第一张设计稿可以看…

10.函数

10.1为什么需要函数 ●函数: function,是被设计为 执行特定任务的代码块 ●作用: 精简代码方便复用(实现代码复用,提高开发效率) 比如我们前面使用的alert()、prompt() 和console.log()都是一些js函数,只不…

编译/反编译

1.Android APK 1.软件 1.apktool 1.作用:反编译apk或重新打包apk 2.dex2jar 1.作用:将Android的可执行文件.dex转换为.jar 3.jd-gui 1.作用:方便阅读jar文件的代码工具 2.步骤 1.通过apktool将apk软件反编译2.使用dex2jar将classes.dex文件转…

(十五) InfluxDB服务进程参数(influxd命令的用法)

以下内容来自 尚硅谷,写这一系列的文章,主要是为了方便后续自己的查看,不用带着个PDF找来找去的,太麻烦! 第 15 章 InfluxDB服务进程参数(influxd命令的用法) 15.1 influxd命令罗列 1、我们的…

Django 图书管理系统

一、功能及页面设计 二、页面展示 (1)首页 (2)注册 (3)登录 (4)普通用户登录 4.1查看图书页面 4.2查看图书详情页 4.3修改密码 (5)管理员登录 5.1添加图书 5.2添加图片 三、代码展示 因为代码太多不好一个个展示 所以需要源码的小伙伴可以找我要代码 感谢三连支持&#xff0…

【C++】多态原理剖析,Visual Studio开发人员工具使用查看类结构cl /d1 reportSingleClassLayout

author:&Carlton tag:C topic:【C】多态原理剖析,Visual Studio开发人员工具使用查看类结构cl /d1 reportSingleClassLayout website:黑马程序员C tool:Visual Studio 2019 date:2023年7月24日 目…

最快桌面UI:Siticone Desktop UI 2.1.1 cRACK

富图尔主义控制 80 多个 .NET UI 组件和控件 现代未来 UI/UX 组件 为 Visual Studio 开发做好准备 无限的免费产品支持案例 超轻量和快速性能 广泛可定制和主题化 低资源消耗和占地面积 免版税开发和部署 NET 的最佳 UI 和 UX 库 从最好的图书馆探索无缝流畅的体验 使…

二、SQL-5.DQL-9.执行顺序

一、案例: 查询年龄大于15的员工的姓名、年龄,并根据年龄进行升序排序 select name, age from emp where age > 15 order by age asc; 先执行①from(定义emp的别名为e),再执行②where(调用别名e&…

SpringBoot集成Druid实现数据库连接池

一、引入依赖 完整的pom文件如下所示: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http…

如何从任何地方远程解决电脑问题?

​如何远程解决电脑问题&#xff1f; “嗨&#xff01;我有一台Windows 10家用电脑。我外出旅行&#xff0c;但我的家人告诉我我的电脑有一段时间无法正常工作。我该如何远程检查电脑并解决相应的问题&#xff1f;提前谢谢&#xff01;” 您是否正在寻找远程解决电…

JAVA解析EXCEL(JExcelAPI,POI,EasyExcel)

前言 文章目录 前言JExcelAPIDemo POIHSSFWorkBookXSSFWorkBookDemo SXSSFWorkBookDemo XSSFReaderDemo EasyExcelDemo demo代码&#xff1a;https://github.com/RwTo/excel-demo JAVA解析Excel 一般有三种方式 JExcelAPI POI EasyExcel JExcelAPI 官网&#xff1a;https://je…

【问题记录】Ubuntu 22.04 环境下,程序报:段错误(核心已转储)怎么使用 core 文件和GDB调试器 解决?

目录 环境 问题情况 解决思路 原因分析 解决方法 番外知识 环境 VMware Workstation 16 Pro &#xff08;版本&#xff1a;16.1.2 build-17966106&#xff09;ubuntu-22.04.2-desktop-amd64 问题情况 本人在运行百万并发的服务端程序时&#xff0c;程序运行报&#xff1a…

【云原生】Docker镜像的创建,Dockerfile

一、Docker镜像的创建 创建镜像有三种方法&#xff0c;分别为【基于已有镜像创建】、【基于本地模板创建】以及【基于Dockerfile创建】。 1.基于现有镜像创建 &#xff08;1&#xff09;首先启动一个镜像&#xff0c;在容器里做修改docker run -it --name web centos:7 /bin/…

UDS之27服务

SecurityAccess&#xff08;0x27&#xff09;—— 安全访问 这个服务的目的是为那些限制访问&#xff0c;以及和排放、安全相关的一些服务和数据提供一些访问权限来保护数据。 此服务执行步骤如下&#xff1a; &#xff08;1&#xff09;Client请求一个种子&#xff08;Seed…

可证明安全初步(Provable Security Basics)

Speecher: Bingsheng Zhang 这一系列的课程&#xff0c;为了介绍一些基础&#xff0c;弥补一些上密码学课和看论文的Gap。 历史上的密码学是art&#xff0c;就像鲁班锁&#xff0c;看着很精妙&#xff0c;但是没有证明。 1970s以来&#xff0c;逐渐发展成Science。 定义和模…

Vue3 axios数据请求封装

Vue3 axios数据请求封装 环境&#xff1a;vue3tsvite 首先在项目目录下安装axios 运行 npm install axios 成功后在package.json文件会显示。 目录&#xff1a; request.ts文件代码&#xff1a; import axios from axiosconst request axios.create({baseURL:https://api.…