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

Java学习-JVM

目录

1. 基本常识

1.1 JVM是什么

1.2 JVM架构图

1.3 Java技术体系

1.4 Java与JVM的关系

2. 类加载系统

2.1 类加载器种类

2.2 执行顺序

2.3 类加载四个时机

2.4 生命周期

2.5 类加载途径

2.6 双亲委派模型

3. 运行时数据区

3.1 运行时数据区构成

3.2 堆

3.3 栈

3.4 本地方法栈

3.5 方法区

3.6 程序计数器

3.7 字符串常量池

4. 对象生命周期

4.1 创建过程

4.2 对象内存分配方式

4.3 内存分配安全问题

4.4 对象分配流程

4.5 对象怎样才会进入老年代

4.6 老年代的担保示意图

4.7 对象三个区

4.8 标记字段

4.9 打印对象内存布局信息

4.10 如何访问对象

5. 垃圾回收

5.1 什么是垃圾

5.2 如何找到垃圾

5.2.1 引用计数法

5.2.2 根可达算法

5.3 回收过程

5.4 对象引用

5.5 如何清除垃圾

5.5.1 标记清除算法 

5.5.2 拷贝算法 

5.5.3 标记-整理算法

5.6 垃圾回收器

5.7 串行收集器

5.7.1 Serial收集器

5.7.2 Serial Old收集器

5.8 并行收集器

5.8.1 Parallel Scavenge收集器

5.8.2 Parallel Old收集器 

5.8.3 ParNew收集器

5.8.4 CMS收集器 

5.8.5 G1(Garbage-First)收集器 

5.8.6 ZGC(Z Garbage Collector) 


1. 基本常识

1.1 JVM是什么

jvm

1.2 JVM架构图

jvm

1.3 Java技术体系

jvm

1.4 Java与JVM的关系

jvm

2. 类加载系统

2.1 类加载器种类

JVM的类加载是通过ClassLoader及其子类来完成的

jvm

jvm

jvm

2.2 执行顺序

jvm

2.3 类加载四个时机

jvm

2.4 生命周期

jvm

2.5 类加载途径

jvm

2.6 双亲委派模型

jvm

jvm

jvm

jvm

3. 运行时数据区

3.1 运行时数据区构成

堆 栈 本地方法栈 方法区 程序计数器

jvm

3.2 堆

概念:

jvm

内存划分: 

jvm

jvm

内存模型变迁: 

jvm

jvm

3.3 栈

栈帧:

jvm

当前栈帧:

jvm

栈帧创建时间: 

jvm

栈异常的两种情况: 

jvm

3.4 本地方法栈

jvm

3.5 方法区

方法区概念:

jvm

方法区存的数据: 

jvm

jvm

永久代与元空间区别: 

jvm

jvm

方法区实现变迁历史: 

jvm

3.6 程序计数器

jvm

3.7 字符串常量池

jvm

jvm

4. 对象生命周期

4.1 创建过程

jvm

4.2 对象内存分配方式

内存分配的方法有两种:不同垃圾收集器不一样

  • 指针碰撞(Bump the Pointer)
  • 空闲列表(Free List)

jvm

jvm

4.3 内存分配安全问题

在分配内存的时候,虚拟机给A线程分配内存过程中,指针未修改。此时B线程同时使用了同样一块内 存。是不是就出现了线程的安全性问题?

在JVM中有两种解决办法:

  1. CAS 是乐观锁的一种实现方式。虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性。
  2. TLAB本地线程分配缓冲(Thread Local Allocation Buffer即TLAB):为每一个线程预先分配一块内存

JVM在第一次给线程中的对象分配内存时,首先进行TLAB的分配。当对象大于TLAB中的剩余内 存或TLAB的内存已用尽时,再采用上述的CAS进行内存分配。

4.4 对象分配流程

jvm

4.5 对象怎样才会进入老年代

对象内存分配:

  • 新生代:新对象大多数都默认进入新生代的Eden区
  • 进入老年代的条件:四种情况
    1:存活年龄太大,默认超过15次【-XX:MaxTenuringThreshold】
    2:动态年龄判断:MinorGC之后,发现Survivor区中的一批对象的总大小大于了这块Survivor区 的50%,那么就会将此时大于等于这批对象年龄最大值的所有对象,直接进入老年代。
    3:大对象直接进入老年代:前提是Serial和ParNew收集器
    4:MinorGC后,存活对象太多无法放入Survivor

空间担保机制:当新生代无法分配内存的时候,我们想把新生代的老对象转移到老年代,然后把新对象 放入腾空的新生代。此种机制我们称之为内存担保。

4.6 老年代的担保示意图

jvm

4.7 对象三个区

jvm

堆内存中,一个对象在内存中存储的布局可以分为三块区域:

  1. 对象头(Header):Java对象头占12字节,数组加4字节
  • 标记字段MarkWord:
    用于存储对象自身的运行时数据,它是synchronized实现轻量级锁和偏向锁的关键。
    默认存储:对象HashCode、GC分代年龄、锁状态等等信息。
    为了节省空间,也会随着锁标志位的变化,存储数据发生变化

  • 类型指针KlassPoint:
    是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
    开启指针压缩存储空间4byte,不开启8byte。
    JDK1.6+默认开启

  • 数组长度:如果对象是数组,则记录数组长度,占4个byte,如果对象不是数组则不存在。

  1. 实例数据(Instance Data):生成对象的时候,对象的非静态成员变量也会存入堆空间

  2. 对齐填充(Padding):JVM内对象都采用8byte对齐,不够8byte的会自动补齐。

4.8 标记字段

在32位系统中,一个字是32bit,也就是4字节。64位系统中,一个字是64bit,也就是8字节。

jvm

4.9 打印对象内存布局信息

<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>import org.openjdk.jol.info.ClassLayout;
public class ObjLock01 {
public static void main(String[] args) {
Object o = new Object();
System.out.println("new Object:" +
ClassLayout.parseInstance(o).toPrintable());
}
}

结论:空对象大小 = 对象头12 + 实例数据0 + 对齐填充4 = 16 bytes

4.10 如何访问对象

有两种方式:

  1. 句柄:稳定,对象被移动只要修改句柄中的地址
  2. 直接指针:访问速度快,节省了一次指针定位的开销

jvm

jvm

5. 垃圾回收

5.1 什么是垃圾

在内存中,没有被引用的对象就是垃圾。

5.2 如何找到垃圾

5.2.1 引用计数法

1、引用计数法(Reference Counting)

jvm​​

 当这个对象引用都消失了,消失一个计数减一,当引用都消失了,计数就会变为0。此时这个对象就会变 成垃圾

在堆内存中主要的引用关系有如下三种:单一引用、循环引用、无引用(垃圾)

5.2.2 根可达算法

2、根可达算法(GCRoots Tracing)

基本思路就是通过一系列的名为“GCRoot”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的 路径称为引用链(Reference Chain),当一个对象到GCRoot没有任何引用链相连时,则证明此对象 是不可用的,也就是不可达的。

可作GCRoots的对象:

  • 虚拟机栈中,栈帧的本地变量表引用的对象。
  • 方法区中,类静态属性引用的对象。
  • 方法区中,常量引用的对象。
  • 本地方法栈中,JNl引用的对象。

5.3 回收过程

即使在可达性分析算法中不可达的对象,也并非是“非死不可”。被判定不可达的对象处于“缓刑”阶段。 要真正宣告死亡,至少要经历两次标记过程:
第一次标记:如果对象可达性分析后,发现没有与GC Roots相连接的引用链,那它将会被第一次标 记;
第二次标记:第一次标记后,接着会进行一次筛选。筛选条件:此对象是否有必要执行 finalize() 方法。在 finalize() 方法中没有重新与引用链建立关联关系的,将被进行第二次标 记。

第二次标记成功的对象将真的会被回收,如果失败则继续存活

5.4 对象引用

在JDK1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(StrongReference)、软引用 (SoftReference)、弱引用(WeakReference)、虚引用(PhantomReference)四种,这四种引 用强度依次逐渐减弱

jvm​​

  1. 强引用
    代码中普遍存在,只要强引用还在,就不会被GC。
Object obj = new Object();
  1. 软引用
    非必须引用,内存溢出之前进行回收,如内存还不够,才会抛异常。
Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
Object o = sf.get();//有时候会返回null
System.out.println("o = " + o);

应用场景:软引用可用来实现内存敏感的高速缓存。

  1. 弱引用

非必须引用,只要有GC,就会被回收。

Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
//System.gc();
Object o = wf.get();//有时候会返回null
boolean enqueued = wf.isEnqueued();//返回是否被垃圾回收器标记为即将回收的垃圾
System.out.println("o = " + o);
System.out.println("enqueued = " + enqueued);

弱引用是在第二次垃圾回收时回收,短时间内通过弱引用取对应的数据,可以取到,当执行过第二 次垃圾回收时,将返回null。
作用:监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方 法返回对象是否被垃圾回收器标记。

  1. 虚引用

虚引用是最弱的一种引用关系。垃圾回收时直接回收

一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对 象实例

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj, new
ReferenceQueue<>());
obj=null;
Object o = pf.get();//永远返回null
boolean enqueued = pf.isEnqueued();//返回是否从内存中已经删除
System.out.println("o = " + o);
System.out.println("enqueued = " + enqueued);

虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也 被成为幽灵引用。
作用:跟踪对象被垃圾回收的状态,仅仅是提供一种确保对象被回收后,做某些事情的机制。类似 事件监听机制

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj, new
ReferenceQueue<>());
obj=null;
Object o = pf.get();//永远返回null
boolean enqueued = pf.isEnqueued();//返回是否从内存中已经删除
System.out.println("o = " + o);
System.out.println("enqueued = " + enqueued);   

5.5 如何清除垃圾

JVM提供3种方法,清除垃圾对象:

  • Mark-Sweep 标记清除算法
  • Copying 拷贝算法
  • Mark-Compact 标记压缩算法

5.5.1 标记清除算法 

1)标记清除算法(Mark-Sweep)
最基本的算法,主要分为标记和清除2个阶段。首先标记出所有需要回收的对象,在标记完成后统一回收 掉所有被标记的对象

jvm​​

缺点:
效率不高,标记和清除过程的效率都不高
空间碎片,会产生大量不连续的内存碎片,会导致大对象可能无法分配,提前触发GC

5.5.2 拷贝算法 

2)拷贝算法(Copying)

为解决效率。它将可用内存按容量划分为相等的两块,每次只使用其中的一块。当这一块的内存用完 了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
现在商业虚拟机都是采用这种收集算法来回收新生代,当回收时,将Eden和Survivor中还存活着的对象 拷贝到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor的空间。
HotSpot虚拟机默认Eden和Survivor的大小比例是8:1,也就是每次新生代中可用内存空间为整个新生 代容量的90%(80%+10%),只有10%的内存是会被“浪费”的。当Survivor空间不够用时,需要依赖其 他内存(这里指老年代)进行分配担保(Handle Promotion)

jvm​​

优点:没有碎片化,所有的有用的空间都连接在一起,所有的空闲空间都连接在一起

缺点:存在空间浪费

5.5.3 标记-整理算法

3)标记-整理算法(Mark-Compact)

老年代没有人担保,不能用复制回收算法。可以用标记-整理算法,标记过程仍然与“标记-清除”算法一 样,然后让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

jvm​​

缺点:性能较低,因为除了拷贝对象以外,还需要对象内存空间进行压缩,所以性能较低。

当前商业虚拟机都是采用这种算法。根据对象的存活周期的不同将内存划分为几块。
新生代,每次垃圾回收都有大量对象失去,选择复制算法。
老年代,对象存活率高,无人进行分配担保,就必须采用标记清除或者标记整理算法

5.6 垃圾回收器

有 8 种不同的垃圾回收器,它们分别用于不同分代的垃圾回收。
新生代回收器:Serial、ParNew、Parallel Scavenge
老年代回收器:Serial Old、Parallel Old、CMS
整堆回收器:G1、ZGC

5.7 串行收集器

使用单线程进行垃圾回收的收集器,每次回收时,串行收集器只有一个工作线程,对于并行能力较弱的 计算机来说,串行收集器性能会更好。

计算机来说,串行收集器性能会更好。 串行收集器可以在新生代和老年代中使用,根据作用于不同的堆空间,分为新生代串行收集器和老年代 收集器。

配置参数 -XX:+UseSerialGC :年轻串行(Serial),老年串行(Serial Old)

5.7.1 Serial收集器

1、Serial收集器:年轻串行

Serial收集器是新生代收集器,单线程执行,使用复制算法。
进行垃圾收集时,必须暂停其他所有的工作线程。
对于单个CPU的环境来说,Serial收集器由于没有线程交互的开销,收集效率更高。

jvm​​

5.7.2 Serial Old收集器

2、Serial Old收集器:老年串行

Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法。

5.8 并行收集器

5.8.1 Parallel Scavenge收集器

1、 Parallel Scavenge收集器

配置参数: -XX:+UseParallelGC
目标是达到一个可控制的吞吐量(Throughput)

特点:
吞吐量优先收集器
新生代使用并行回收收集器,采用复制算法
老年代使用串行收集器

jvm​​

5.8.2 Parallel Old收集器 

2、 Parallel Old收集器

配置参数: -XX:+UseParallelOldGC

特点: Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
在注重吞吐量,CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器。

jvm​​

5.8.3 ParNew收集器

3、ParNew收集器

配置参数: -XX:+UseParNewGC
配置参数: -XX:ParallelGCThreads=n 设置并行收集器收集时使用的并行收集线程数。一般最好和计 算机的CPU相当

特点:
新生代并行(ParNew),老年代串行(Serial Old)
Serial收集器的多线程版本

注意:单CPU性能并不如Serial,因为存在线程交互的开销

jvm​​

5.8.4 CMS收集器 

4、CMS收集器

配置参数: -XX:+UseConcMarkSweepGC 应用CMS收集器。

尽管CMS收集器采用的是并发回收,但是在其初始标记和重新标记这两个阶段中仍然需要执行“STW”暂 停程序中的工作线程,不过暂停时间并不会太长,目前所有的垃圾收集器都做不到完全不需要“STW”, 只是尽可能地缩短暂停时间。
由于最耗费时间的并发标记与并发清除阶段都不需要暂停工作,所以整体的回收是低停顿的。另外,由 于在垃圾收集阶段用户线程没有中断,所以在CMS回收过程中,还应该确保应用程序用户线程有足够的 内存可用

特点:
低延迟:减少STW对用户体验的影响【低延迟要求高】
并发收集:可以同时执行用户线程
CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,而是当堆内存使用率 达到某一阈值时,便开始进行回收。
CMS收集器的垃圾收集算法采用的是标记-清除算法, 会产生内存碎片,导致并发清除后,用户线程可用的空间不足。
CMS收集器对CPU资源非常敏感。

jvm​​

CMS整个过程比之前的收集器要复杂,整个过程分为4个主要阶段:
初始标记(Initial-Mark)阶段:
本阶段任务:标记出GCRoots能直接关联到的对象。
一旦标记完成之后就会恢复之前被暂停的所有应用线程。
由于直接关联对象比较小,所以这里的速度非常快。
会STW
并发标记(Concurrent-Mark)阶段:
本阶段任务:从GC Roots的直接关联对象遍历整个对象图
这个过程耗时较长
不会STW
重新标记(Remark)阶段:
本阶段任务:修正并发标记期间,因用户程序继续运作产生的新的对象记录
这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短。
会STW
并发清除(Concurrent-Sweep)阶段:
本阶段任务:清理删除掉标记阶段判断的已经死亡的对象,释放内存空间。
由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。

5.8.5 G1(Garbage-First)收集器 

5、 G1(Garbage-First)收集器
Garbage First(简称G1)收集器是垃圾收集器技术发展历史上的里程碑式的成果,它开创了收集器面向 局部收集的设计思路和基于Region的内存布局形式。

G1是一款面向服务端应用的垃圾收集器,大内存企业配置的垃圾收集器大多都是G1。
JDK 9发布之日G1宣告取代Parallel Scavenge加Parallel Old组合,成为服务端模式下的默认垃圾收 集器,而CMS则被声明为不推荐使用(Deprecate)。

G1最大堆内存是 32MB2048=64G ,G1最小堆内存 1MB2048=2GB ,低于此值建议使用其它收集器。

特点:

  1. 并行与并发:充分利用多核环境下的硬件优势
  2. 多代收集:不需要其他收集器配合就能独立管理整个GC堆
  3. 空间整合:“标记-整理”算法实现的收集器,局部上基于“复制”算法不会产生内存空间碎片
  4. 可预测的停顿:能让使用者明确指定消耗在垃圾收集上的时间。当然,更短的GC时间的代价是回 收空间的效率降低。

jvm​​

G1收集器的运作大致可划分为以下几个步骤:

  1. 初始标记:标记一下GC Roots能直接关联到的对象,需要停顿线程,但耗时很短
  2. 并发标记:是从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但 可与用户程序并发执行
  3. 最终标记:修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录
  4. 筛选回收:对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收 计划
    G1中有三种模式垃圾回收模式,Young GC、Mixed GC 和 Full GC,在不同的条件下被触发。

G1内存划分
G1垃圾收集器相对比其他收集器而言,最大的区别在于它取消了新生代、老年代的物理划分,取而代之 的是将堆划分为若干个区域(Region),这些区域中包含了有逻辑上的新生代、老年代区域。
好处:不用单独的空间对每个代进行设置,不用考虑每个代内存如何分配。

局部采用复制算法:
G1新生代垃圾收集依然采用暂停所有应用线程的方式,将存活对象拷贝到老年代或者Survivor空间
G1通过将对象从一个区域复制到另外一个区域,完成了清理工作。 相当于在正常的处理过程中, G1完成了堆的压缩,这样就不会有cms内存碎片问题了。

Humongous区域:在G1中,有一种特殊的区域叫Humongous区域
如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象。 这些巨 型对象,默认直接会被分配在老年代。
但是,如果是一个短期存在的巨型对象,在分区之间来回拷贝,就会对垃圾收集器造成负面影响。 为了解决这个问题,G1划分了Humongous区,它用来专门存放巨型对象。如果一个H区装不下一 个巨型对象,那么G1会寻找连续的H分区来存储。

-XX:+UseG1GC
# 使用 G1 垃圾收集器
-XX:MaxGCPauseMillis=
# 设置期望达到的最大GC停顿时间指标(JVM会尽力实现,但不保证达到),默认值是 200 毫秒。
-XX:G1HeapRegionSize=n
# 设置的 G1 区域的大小。值是 2 的幂,范围是 1 MB 到 32 MB 之间。
# 目标是根据最小的 Java 堆大小划分出约 2048 个区域。
# 默认是堆内存的1/2000。
-XX:ParallelGCThreads=n
# 设置并行垃圾回收线程数,一般将n的值设置为逻辑处理器的数量,建议最多为8。
-XX:ConcGCThreads=n
# 设置并行标记的线程数。将n设置为ParallelGCThreads的1/4左右。
-XX:InitiatingHeapOccupancyPercent=n
# 设置触发标记周期的 Java 堆占用率阈值。默认占用率是整个 Java 堆的 45%。

5.8.6 ZGC(Z Garbage Collector) 

6、ZGC(Z Garbage Collector)

Z Garbage Collector,也称为ZGC,在 JDK11 中引入的一种可扩展的低延迟垃圾收集器,在 JDK15 中 发布稳定版

ZGC的目标:
< 1ms 最大暂停时间(jdk < 16 是 10ms,jdk >=16 是 <1ms )
暂停时间不会随着堆、live-set 或 root-set 的大小而增加
适用内存大小从 8MB 到16TB 的堆

ZGC 具有以下特征:
并发
基于 region
压缩
NUMA 感知
使用彩色指针
使用负载屏障

ZGC 收集器是一款基于 Region 内存布局的, 不设分代的,使用了读屏障、染色指针和内存多重映射等 技术来实现可并发的标记-整理算法的,以低延迟为首要目标的一款垃圾收集器。ZGC 的核心是一个并发 垃圾收集器,这意味着所有繁重的工作都在Java 线程继续执行的同时完成。这极大地限制了垃圾收集对 应用程序响应时间的影响。

-XX:+UseZGC # 启用 ZGC
-Xmx # 设置最大堆内存
-Xlog:gc # 打印 GC日志
-Xlog:gc* # 打印 GC 详细日志

总结:
在众多的垃圾回收器中,没有最好的,只有最适合应用的回收器,根据应用软件的特性以及硬件平台的 特点,选择不同的垃圾回收器,才能有效的提高系统性能。【小马拉大车、大车驮小马的现象都不合 理!】

相关文章:

Java学习-JVM

目录 1. 基本常识 1.1 JVM是什么 1.2 JVM架构图 1.3 Java技术体系 1.4 Java与JVM的关系 2. 类加载系统 2.1 类加载器种类 2.2 执行顺序 2.3 类加载四个时机 2.4 生命周期 2.5 类加载途径 2.6 双亲委派模型 3. 运行时数据区 3.1 运行时数据区构成 3.2 堆 3.3 栈…...

leed认证分几个级别

LEED&#xff08;Leadership in Energy and Environmental Design&#xff09;认证是一个评估建筑项目可持续性的严格框架&#xff0c;其级别主要分为以下四个&#xff1a; LEED认证&#xff08;Certified&#xff09;&#xff1a;这是最低级别的认证&#xff0c;要求建筑项目…...

3.C++经典实例-计算一个数的阶乘

阶乘&#xff08;factorial&#xff09;是‌基斯顿卡曼于1808年发明的运算符号&#xff0c;用于表示一个正整数n的所有小于及等于该数的正整数的积。自然数n的阶乘写作n!。例如&#xff0c;5的阶乘表示为5! 1 2 3 4 5 120。 阶乘在数学和计算机科学中有广泛的应用。例如…...

深入理解Qt中的QTableView、Model与Delegate机制

文章目录 显示效果QTableViewModel(模型)Delegate(委托)ITEM控件主函数调用项目下载在Qt中,视图(View)、模型(Model)和委托(Delegate)机制是一种非常强大的架构,它们实现了MVC(模型-视图-控制器)设计模式。这种架构分离了数据存储(模型)、数据展示(视图)和数据操作(委托),使…...

解读《ARM Cortex-M3 与Cortex-M4 权威指南》——第1章 ARM Cortex-M处理器简介

1. 三级流水线设计 解释:三级流水线设计意味着处理器在执行指令时可以同时处理多个步骤。这些步骤通常包括取指(Fetch)、译码(Decode)和执行(Execute)。好处:这种设计提高了指令的执行效率,使得处理器能够在每个时钟周期内完成更多的工作,从而提升整体性能。2. 哈佛总…...

java集合类的框架体系

1.集合的好处 相比数组&#xff0c;他可以存储多种类型的元素&#xff0c;并且可以动态新增&#xff1b; 2. 集合分类 3.Collection接口 3.1常用方法 3.2迭代器-遍历 collection接口继承了Interable接口&#xff0c;collection的子类可以使用迭代器&#xff1b; 注意事项…...

基于SpringBoot+Vue+Uniapp家具购物小程序的设计与实现

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而…...

什么是模糊测试?

近年来&#xff0c;随着信息技术的发展&#xff0c;各种新型自动化测试技术如雨后春笋般出现。其中&#xff0c;模糊测试&#xff08;fuzz testing&#xff09;技术开始受到行业关注&#xff0c;它尤其适用于发现未知的、隐蔽性较强的底层缺陷。这里&#xff0c;我们将结合AFL开…...

3.C++经典实例-奇数还是偶数

要判断一个数是奇数还是偶数&#xff0c;只需要判断这个数是否能被2整除即可&#xff0c;如果要判断是否能整除&#xff0c;则要判断当前数除以2的余数是否为0&#xff0c;在C中&#xff0c;余数&#xff0c;使用%号&#xff0c;因此&#xff0c;程序为&#xff1a; #include …...

真牛啊!全球人工智能标准教科书,斯坦福、麻省理工、加州大学等十多所顶尖机构为它点赞!!

这本《人工智能&#xff1a;计算代理基础》堪称全球人工智能标准教科书&#xff01;它因其前沿的技术融合、丰富的实践案例以及理论深度与实践并重的特点而成为人工智能领域的热门书籍。 该书已经赢得了斯坦福大学、佐治亚理工学院、谷歌大脑、麻省理工学院、加州大学、微软研究…...

Android——通过MediaStore查询图片

查询图片&#xff1a; private void loadImageList() {String[] columns new String[]{MediaStore.Images.Media._ID, // 编号MediaStore.Images.Media.TITLE, // 标题MediaStore.Images.Media.SIZE, // 文件大小MediaStore.Images.Media.DATA, // 文件路径};Cursor cursor g…...

手写Spring IOC-简易版

目录 项目结构entitydaoIUserDaoUserDaoImpl serviceIUserServiceUserServiceImpl ApplicationContext 配置文件初始化 IOC 容器RunApplication 注解初始化 IOC 容器BeanAutowired Reference 项目结构 entity User Data NoArgsConstructor AllArgsConstructor Accessors(chai…...

【算法题】62. 不同路径(LeetCode)

【算法题】62. 不同路径(LeetCode) 1.题目 下方是力扣官方题目的地址 62. 不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图…...

【VUE】Vue中的data属性为什么是一个函数而不是一个对象

在 Vue.js 中&#xff0c;组件的 data 属性可以是一个对象或者一个函数但通常建议将其设置为函数。这是因为组件可能会被多次使用&#xff0c;如果 data 是一个普通对象&#xff0c;那么该对象会被所有实例共享&#xff0c;导致数据混乱。将 data 设置为一个函数可以保证每个组…...

ddos攻击介绍和排查方法

一、DDoS攻击介绍 DDoS攻击&#xff0c;全称为分布式拒绝服务攻击&#xff08;Distributed Denial of Service Attack&#xff09;&#xff0c;是一种常见的网络攻击手段。它通过利用多个计算机系统向目标服务器、服务或网络发送大量请求&#xff0c;导致目标无法处理正常流量…...

git clone --single-branch 提升效率

git clone --single-branch 是一个Git命令&#xff0c;用于从远程仓库中仅克隆单个分支到本地仓库。这个命令在软件开发中非常有用&#xff0c;尤其是在需要特定分支的代码而无需整个仓库的情况下。 基本用法 git clone --single-branch 命令的基本语法如下&#xff1a; git…...

代码随想录算法训练营第十天|1. 两数之和,第454题.四数相加II

文档讲解&#xff1a;代码随想录 难度&#xff1a;一般嗷~~ 1. 两数之和 力扣题目链接(opens new window) 给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为目标值的那 两个 整数&#xff0c;并返回他们的数组下标。 你可以假设每种输入只会对…...

龙迅LT8911EX LVDS转EDP 点屏,大批量出货产品

龙迅LT8911EX描述&#xff1a; Lontium LT8911EX是LVDS到eDP转换器&#xff0c;具有单端口或双端口可配置的LVDS接收器&#xff0c;有1个时钟通道和最多8个数据通道&#xff0c;每个数据通道最大运行1.2Gbps&#xff0c;最大输入带宽为9.6Gbps。转换器将输入LVDS数据去序列化&…...

浅谈Oracle之游标

一、基本介绍 在Oracle数据库中&#xff0c;游标&#xff08;Cursor&#xff09;是一种强大的工具&#xff0c;用于逐行处理查询结果集。然而&#xff0c;游标的使用需要谨慎&#xff0c;因为不当的使用可能会导致性能问题。 二、最佳实践和优化技巧 尽量避免使用游标&#xf…...

基于在线教育系统源码的企业培训平台开发解决方案详解

本篇文章&#xff0c;笔者将详细解析基于在线教育系统源码开发企业培训平台的解决方案&#xff0c;探讨其开发步骤、关键功能模块及技术实现方案。 一、在线教育系统源码的优势 在构建企业培训平台时&#xff0c;选择基于在线教育系统源码的开发方式具有以下几个显著优势&…...

Whisper 音视频转写

Whisper 音视频转写 API 接口文档 api.py import os import shutil import socket import torch import whisper from moviepy.editor import VideoFileClip import opencc from fastapi import FastAPI, File, UploadFile, Form, HTTPException, Request from fastapi.respons…...

【详尽-实战篇】使用Springboot生成自带logo或者图片的二维码-扫描二维码可以跳转到指定的页面-Zing-core

先上效果图 项目源码&#xff1a;https://download.csdn.net/download/qq_43055855/89891285 源码地址 手机扫描二维码跳转到指定网页 概述 这个项目是一个基于 Java 的二维码生成与解析工具&#xff0c;主要由 QRCodeUtil 和 QRCodeController 两个类组成。它利用了 Google…...

vue跨标签页通信(或跨窗口)详细教程

在 Vue 应用中,跨标签页(或跨窗口)的通信通常涉及到两个或多个浏览器标签页之间的信息共享。由于每个标签页或窗口都是独立的 JavaScript 执行环境,它们不能直接通过 Vue 或其他 JavaScript 库来直接相互通信。但是,有一些方法可以实现这种跨标签页的通信,主要依靠浏览器…...

【VUE】Vue3通过数组下标更改数组视图为什么会更新?

在 Vue 3 中&#xff0c;使用 Proxy 来实现了对数组的响应式监听&#xff0c;相比于 Vue 2 使用的 Object.defineProperty()&#xff0c;Proxy 更加高效和灵活。 因此&#xff0c;在 Vue 3 中&#xff0c;通过数组下标直接更改数组中某一项的值&#xff0c;也能够被 Vue 正确监…...

前端转换double数据,保留两位小数

Number Number(1.00) 1 Number(1.10) 1.1 Number(1.101) 1.101 要想前端展示页面按 1.00展示1&#xff0c;1.10 展示1.1 需要套一个number() 1.1 保留两位小数&#xff0c;并三位一个分隔符 indexView.value[key] formatNumber(indexView.value[key].toFixed(2))//格式…...

【实战案例】JSR303统一校验与SpringBoot项目的整合

前后端分离项目中&#xff0c;当前前端请求后端接口的时候通常需要传输参数&#xff0c;对于参数的校验应该在哪一步进行校验&#xff1f;Controller中还是Service中&#xff1f;答案是都需要校验&#xff0c;只不过负责的板块不一样&#xff0c;Controller中通常校验请求参数的…...

忘记了系统root密码,如何重置root密码?

重置root密码&#xff08;CentOS7&#xff09; 文章目录 重置root密码&#xff08;CentOS7&#xff09;[toc] 1.开启系统时&#xff0c;在引导界面按下字母e。 2.进入到内核界面&#xff0c;找到Linux开头字样一行&#xff0c;然后在最末尾输入参数rd.break&#xff0c;然后按住…...

7-基于国产化FT-M6678+JFM7K325T的6U CPCI信号处理卡

一、板卡概述 本板卡系我公司自主研发&#xff0c;基于6U CPCI的通用高性能信号处理平台。板卡采用一片国产8核DSP FT-C6678和一片国产FPGA JFM7K325T-2FFG900作为主处理器。为您提供了丰富的运算资源。如下图所示&#xff1a; 二、设计参考标准 ● PCIMG 2.0 R3.0 CompactP…...

计算机毕业设计 | SSM超市进销存管理系统(附源码)

1&#xff0c;绪论 1.1 开发背景 世界上第一个购物中心诞生于美国纽约&#xff0c;外国人迈克尔库伦开设了第一家合作商店&#xff0c;为了更好地吸引大量客流量&#xff0c;迈克尔库伦精心设计了低价策略&#xff0c;通过大量进货把商品价格压低&#xff0c;通过商店一次性集…...

手撕数据结构 —— 堆(C语言讲解)

目录 1.堆的认识 什么是堆 堆的性质 2.堆的存储 3.堆的实现 Heap.h中接口总览 具体实现 堆结构的定义 初始化堆 销毁堆 堆的插入 堆的向上调整算法 堆的插入的实现 堆的删除 堆的向下调整算法 堆的删除的实现 使用数组初始化堆 获取堆顶元素 获取堆中的数据…...