面试题整理:Java虚拟机 JVM 内存区域、垃圾回收、类加载器
文章目录
- JVM虚拟机
- 内存区域
- 1. ⭐JVM的内存区域有哪些?每个区域的作用是什么?
- 2. 堆和栈的区别是什么?
- 3. 堆内存是如何划分的?
- 4. 永久代和元空间是什么关系?
- 5. 对JVM常量池的理解?
- 6. ⭐Java 对象的创建过程?
- 7. ⭐说说Java的对象内存分配?
- 8. ⭐Java的对象内存布局?
- 9. ⭐对象的访问定位的方式?
- 垃圾回收
- 1. Minor Gc 和 Full GC 有什么不同呢?
- 2. ⭐如何判断对象是否死亡?
- 3. ⭐介绍一下强引用、软引用、弱引用、虚引用?
- 4. 如何判断一个常量是废弃常量?
- 5. 如何判断一个类是无用的类?
- 6. ⭐垃圾收集有哪些算法,各自的特点?
- 7. ⭐常见的垃圾回收器有哪些?重点CMS、G1
- 类加载器
- 1. java类文件结构是什么?
- 2. ⭐java类的生命周期?
- 3. 类加载器的作用?
- 4. Java 中有哪些主要的类加载器?
- 5. 自定义类加载器?
- 6.⭐介绍双亲委派模型?
JVM虚拟机
Java 虚拟机(Java Virtual Machine, JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现,目的是使用相同的字节码,它们都会给出相同的结果。只要满足 JVM 规范,每个公司、组织或者个人都可以开发自己的专属 JVM。我们平时接触到的 HotSpot VM 是 JVM 规范的一种实现,此外还有J9 VM、JRockit VM 等 JVM 。JDK包含JRE包含JVM包含JIT。
内存区域
1. ⭐JVM的内存区域有哪些?每个区域的作用是什么?
Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。
线程私有的:
-
程序计数器:记录当前线程执行的字节码指令地址,字节码解释器通过改变程序计数器实现代码流程控制(唯一无OOM的内存区域)。
-
虚拟机栈:存储方法调用的栈帧,每个栈帧中有局部变量表、操作数栈、动态链接、方法返回地址。
每一个方法调用时压入一个栈帧,每个方法调用结束后弹出一个栈帧。
局部变量表存放存放编译期可知的各种数据类型、对象引用
reference
类型。操作数栈存放执行过程的中间计算结果和临时变量。动态链接是当一个方法要调用其他方法时,把常量池中方法的符号引用转换为内存地址的直接引用。若内存大小不允许动态扩展,线程请求的栈深度超过JVM栈的最大深度时
StackOverflowError
;若允许动态扩展,若虚拟机动态扩展栈时申请不到足够的内存空间则会OOM。 -
本地方法栈:为Native方法服务,类似虚拟机栈。
线程共享的:
-
堆:存放对象实例和数组。GC主要区域,空间不足时抛出
OutOfMemoryError
。JVM管理的内存区域中最大的一块,几乎所有对象实例都分配在堆内存。JDK 1.7 开始已经默认开启逃逸分析,如果某些方法中的对象引用没有被返回或者未被外面使用(未逃逸出去),对象可以直接在栈上分配内存。Java堆是垃圾收集器管理的主要区域,也称为GC堆。堆容易出现OOM,出现后有几种表现形式: JVM 花太多时间执行垃圾回收但只能回收很少的堆空间时
java.lang.OutOfMemoryError: GC Overhead Limit Exceeded
,创建新的对象时堆内存中的空间不足以存放新创建的对象java.lang.OutOfMemoryError: Java heap space
-
方法区:方法区存储被虚拟机加载的类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虚拟机使用一个类时,会读取并解析Class文件获取相关信息并存储到方法区中。
-
直接内存:一种特殊的内存缓冲区,不在Java堆或方法区中分配,而是通过JNI的方式在本地内存上分配。
直接内存不是虚拟机规范中定义的内存区域,不属于运行时数据区部分,但这部分也可能导致OOM。
JDK1.4 中新加入的 NIO(Non-Blocking I/O,也被称为 New I/O),引入了一种基于通道与缓存区的 I/O 方式,它可以直接使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的
DirectByteBuffer
对象作为这块内存的引用进行操作。能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆之间来回复制数据。
2. 堆和栈的区别是什么?
数据存储
- 堆:存储对象实例,线程共享。
- 栈:存储方法调用的栈帧,线程私有。
内存分配
- 堆:动态分配,GC管理,可能产生内存碎片,空间较大但访问速度相对较慢。
- 栈:随着方法调用和结束自动分配和释放,空间较小但访问速度快(移动指针)。
3. 堆内存是如何划分的?
为什么要分为新生代、老年代?结合垃圾回收算法回答,分代划分后可以结合不同分代的数据特点选择合适的垃圾回收算法。
-
新生代:用于存放新生对象。新生代通常比较小,垃圾回收频繁发生。
-
Eden:新创建的对象先分配到Eden区。
当 Eden 区没有足够空间进行分配时,虚拟机将发起一次Minor GC。GC期间JVM发现Eden区的对象无法存入Survivor时,会通过分配担保机制把新生代对象提前转移至老年代,老年代的空间足够存储时就不会Full GC。Minor GC后,继续要分配的对象如果能存放在Eden 区就继续在Eden 区分配内存。
空间分配担保:确保在 Minor GC 之前老年代还有容纳新生代所有对象的剩余空间。
JDK 6 Update 24之后 :只要老年代的连续空间大于新生代对象总大小(Minor GC时安全的)或者历次晋升到老年代对象的平均大小(有担保失败的风险),就会进行 Minor GC,否则将进行 Full GC。
-
Survivor(S0和S1):一次垃圾回收后还存活的对象被移动到Survivor区。年龄变为1。
-
-
老年代:
-
Old:新生代的对象年龄增加到一定年龄阈值时转移到老年代。
年龄阈值:动态年龄计算。Hotspot 遍历所有对象时,按照年龄从小到大对其所占用的大小进行累加,当累加到某个年龄时,所累加的大小超过了 Survivor 区的一半,则取这个年龄和
MaxTenuringThreshold
中更小的一个值,作为新的晋升年龄阈值。参数-XX:MaxTenuringThreshold
值在0-15,因为记录年龄的区域在对象头中,大小为4位。大对象例如字符串数据等需要大量连续内存空间的对象直接进入老年代,长期存活的对象直接进入老年代。避免将大对象放入新生代导致频繁的新生代的垃圾回收,具体怎么多大由垃圾回收器相关参数决定。
-
-
永久代(jdk1.8以前)
- JDK 8 版本之后 PermGen(永久) 已被 Metaspace(元空间) 取代,元空间使用的是直接内存 。
4. 永久代和元空间是什么关系?
JDK1.8
之前方法区由永久代实现,JDK1.8
之后由元空间(Metaspace
)实现。方法区是抽象概念、规范,永久代和元空间是其具体实现。
永久代在运行时数据区域,元空间在本地内存,从永久代调整为元空间的原因:
- 永久代受
JVM
内存限制有固定大小上限且无法调整,元空间使用本地内存,受本机可用内存限制,溢出几率更小。 - 永久代给
GC
带来不必要复杂度且回收效率低。 - 元空间存放类元数据,加载类的数量不由
MaxPermSize
控制,而由系统实际可用空间控制,能加载更多类。 - JDK1.8合并
HotSpot
和JRockit
代码时,JRockit
无永久代,合并后无需额外设置永久代。
5. 对JVM常量池的理解?
class文件中的常量池:
- 存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference)的常量池表。
- 字面量包括整数、浮点数和字符串字面量比如
0 3.14 "abc"
。 - 符号引用包括类符号引用、字段符号引用、方法符号引用、接口方法符号,编译阶段以符号的形式存在,运行阶段被动态链接转换为直接引用。
- 字面量包括整数、浮点数和字符串字面量比如
运行时常量池(在方法区):
- class文件加载到jvm之后,class文件常量池的内容加载到运行时常量池,将符号引用替换成直接引用。
- jvm 在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。当类加载到内存中后,jvm 就会将 class 常量池中的内容存放到运行时常量池中,运行时常量池是每个类都有一个。
字符串常量池(方法区->堆):
-
JVM 为了提升性能和减少内存消耗,针对字符串专门开辟的一块区域,避免字符串的重复创建。
-
HotSpot 虚拟机中字符串常量池的实现是由一个
HashTable
保存字符串key和字符串对象的引用value的映射关系,字符串对象的引用指向堆中的字符串。 -
JDK1.7 存放在方法区(永久代),JDK1.7存放在堆中。转移是因为永久代GC回收效率低,只有
Full GC
时才回收,而java程序中一般会有大量被创建的字符串等待回收。
JDK1.7 之前:运行时常量池<逻辑包含>字符串常量池,存放在方法区, 此时 hotspot 虚拟机对方法区的实现为永久代。
JDK1.7: 字符串常量池被单独从方法区拿到了堆中, 运行时常量池剩下的东西还在方法区, 也就是 hotspot 中的永久代 。
JDK1.8:字符串常量池还在堆, 运行时常量池还在方法区, 只不过方法区的实现从永久代变成了元空间,元空间使用的是直接内存
6. ⭐Java 对象的创建过程?
-
类加载检查。JVM遇到New指令时,先检查能否在运行时常量池中定位到类的符号引用,检查符号引用代表的类是否被加载、解析、初始化过。如果没有,先进行类加载。
-
**分配内存。**完成类加载检查后,JVM为新生对象分配内存,从堆中划分一块内存区域。
内存分配方式包括指针碰撞、空闲列表两种,选择哪种方式取决于java堆是否规整,堆是否规整取决于采用的垃圾收集器是否带有压缩整理的功能。
-
**初始化零值。**将分配到的内存空间初始化为零值(对象头以外的部分),保证对象的实例字段再Java代码中不赋初始值就能够直接使用。
-
<老忘>⭐设置对象头。对对象进行必要的设置,相关信息放在对象头中。这些设置包括对象是哪个类的实例,找到类的元数据信息的方式,对象的哈希码,对象的GC分代年龄信息等。
-
**执行
init
方法。**执行<init>
方法也就是构造方法的内容,按照程序员的逻辑对对象进行初始化操作。
7. ⭐说说Java的对象内存分配?
下面谈谈Java对象的内存分配方式、内存并发问题、内存布局问题。
JVM为新生对象分配内存,需要从堆中划分一块内存区域。
**对象内存分配方式**包括指针碰撞、空闲列表两种,选择哪种方式取决于java堆是否规整,堆是否规整取决于采用的垃圾收集器是否带有压缩整理的功能。
指针碰撞:
- 适用于堆内存规整的情况,没有内存碎片。GC收集器Serial、ParNew。
- 原理:用过的内存整合到一边,没用过的放另一边,中间有一个分界指针,向着没有用过的内存方向把指针移动<对象内存大小>个位置。
空闲列表:
- 适用于堆内存不规整的情况,有内存碎片。GC收集器CMS。
- 原理:JVM维护一个列表,列表记录哪些内存块可用,分配时找一块足够大的内存块划分给对象实例,最后更新列表记录。
对象内存分配并发问题:实际开发时,创建对象比较频繁,虚拟机需要保证线程安全。方式①CAS+失败重试保证更新操作的原子性。②TLAB线程本地分配缓冲:Thread Local Allocation Buffer
,JVM预先为每个线程在Eden区分配一块内存,线程需要创建对象分配内存时,优先在自己的TLAB中分配,如果超过了剩余可用内存的话再采用CAS方式来进行常规的内存分配。
8. ⭐Java的对象内存布局?
对象内存布局:对象在内存中布局分为3块区域,对象头,实例数据,对齐填充。
- 对象头:包括标记字段
Mark Word
、类型指针Klass pointer
,数组对象还有数组长度。- 标记字段:存储对象自身的运行时数据。哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
- 类型指针:对象指向它的类元数据的指针。通过类型指针确定该对象是哪个类的实例。
- 实例数据:对象真正存储的信息,各类型字段内容。
- 对齐填充:起到占位作用,不一定存在。比如Hotspot虚拟机自动内存管理系统要求对象起始地址是8字节的整数倍,如果实例数据没有对齐就通过对齐填充补全。
9. ⭐对象的访问定位的方式?
Java 程序通过栈上局部变量表中的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有:使用句柄、直接指针。
句柄:Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与对象类型数据各自的具体地址信息。优点:reference中存储了稳健的句柄地址,对象被移动时只改变句柄中实例数据的指针,reference本身不修改。
直接指针:直接指针访问,reference 中存储的直接就是对象的地址。优点:速度快,比句柄节省了一次指针定位时间开销。
垃圾回收
1. Minor Gc 和 Full GC 有什么不同呢?
针对 HotSpot VM 的实现,它里面的 GC 准确分类只有两大种:
部分收集 (Partial GC):
- 新生代收集(Minor GC / Young GC):只对新生代进行垃圾收集;
- 老年代收集(Major GC / Old GC):只对老年代进行垃圾收集。需要注意的是 Major GC 在有的语境中也用于指代整堆收集;
- 混合收集(Mixed GC):对整个新生代和部分老年代进行垃圾收集。
整堆收集 (Full GC):收集整个 Java 堆和方法区。
2. ⭐如何判断对象是否死亡?
引用计数法
为对象添加引用计数器,每当被引用,计数器就加1,引用失效时计数器减1,计数器为0的对象不会再被使用。
实现简单,效率高,但目前主流的虚拟机中并没有选择这个算法来管理内存,最主要原因是很难解决对象之间循环引用的问题。
可达性分析算法
通过一系列的称为 “GC Roots” 的对象作为起点,从GC Roots
节点开始搜索,节点所走过的路径称为引用链,当一个对象到GC Roots
没有任何引用链相连时证明此对象不可达,需要被回收。
**哪些对象可以作为 GC Roots 呢?**GC ROOT是一个指针,不是对象
- 虚拟机栈(栈帧中的局部变量表)中引用的对象,本地方法栈(Native 方法)中引用的对象
- 方法区中类静态变量引用的对象,方法区中常量引用的对象
- 所有被同步锁持有的对象
- JNI(Java Native Interface)引用的对象
不可达的对象,并非立即被回收,而是需要经历2次标记过程。
第一次标记:判断当前对象是否有finalize()
方法并且该方法没有被执行过,若不存在则标记为垃圾对象,等待回收;若有的话,并且该方法没有被执行,则进行第二次标记;
第二次标记将当前对象放入 F-Queue 队列,并生成一个 finalizaler 线程执行finalize()
方法,虚拟机不保证该方法一定会被执行,是因为如果线程执行缓慢或进入了死锁,会导致回收系统的崩溃;如果执行了 finalize()
方法之后仍然没有与 GC Roots 有直接或者间接的引用,则该对象会被回收。
Object
类中的finalize
方法影响了 Java 语言的安全和 GC 的性能,会被逐渐弃用移除.
3. ⭐介绍一下强引用、软引用、弱引用、虚引用?
强引用:就是我们平时最常用的普通引用,只要强引用还存在,对象就不会被垃圾回收。
软引用:如果一个对象只被软引用关联,系统内存不足时,会被垃圾回收器回收。常用于实现对内存敏感的缓存。
弱引用:只要垃圾回收器发现只被弱引用关联的对象,不管内存是否充足,都会回收该对象。
虚引用:也叫幽灵引用或幻影引用,它对对象的生存时间没有影响,主要用于跟踪对象被垃圾回收器回收的活动。 虚引用必须和引用队列(ReferenceQueue)联合使用,当垃圾回收器准备回收一个对象时,如果发现还存在虚引用,会在回收对象内存之前把虚引用加入到关联的引用队列中,程序可以通过判断引用队列中是否已经有虚引用来判断对象是否将被垃圾回收。
虚引用与软引用和弱引用的区别主要在于:虚引用不会影响对象的生命周期,而软引用和弱引用会在一定条件下影响对象的回收时机。
使用软引用能带来的好处:可以在内存足够时保留对象,提高系统性能和资源利用率,当内存紧张时又能自动释放对象以避免内存溢出,适用于创建缓存等场景。
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;public class ReferenceExample {public static void main(String[] args) {Object strongRef = new Object();// 强引用SoftReference<Object> softRef = new SoftReference<>(new Object());// 软引用WeakReference<Object> weakRef = new WeakReference<>(new Object());// 弱引用// 虚引用ReferenceQueue<Object> queue = new ReferenceQueue<>();PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);}
}
4. 如何判断一个常量是废弃常量?
看是否有对象引用这个常量。
假如在字符串常量池中存在字符串 “abc”,如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 “abc” 就是废弃常量,如果这时发生内存回收的话而且有必要的话,“abc” 就会被系统清理出常量池了。
5. 如何判断一个类是无用的类?
方法区主要回收的是无用的类,同时满足下面 3 个条件才能算是“无用的类”:对象实例和类加载器被回收,Class对象不被引用
- 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
- 加载该类的
ClassLoader
已经被回收。 - 该类对应的
java.lang.Class
对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
6. ⭐垃圾收集有哪些算法,各自的特点?
标记-清除算法、复制算法、标记-整理算法、分代收集算法
标记-清除算法:标记所有不需要回收的对象,然后统一回收没有被标记的对象。缺点:标记和清除效率低、会产生大量内存碎片。CMS老年代回收算法。
复制算法:内存均分为两块,每次用一块。A块用满后,把存活对象复制到B块中,再把A块中的空间清理掉,每次回收是对内存空间的一半进行回收。缺点:可用内存折半,不适合老年代(存活对象数量比较大时复制性能差),适合新生代。
标记-整理算法:标记不需要回收的对象,让存活对象向一端移动,最后清理掉边界以外的内存。适用于老年代这种回收频率不高的场景。
分代收集算法:目前虚拟机垃圾收集都采用分代收集算法,根据对象存活周期将内存分为新生代、老年代,根据各个年代的特点选择合适的垃圾收集算法。新生代可以选择复制算法,老年代选择标记清除或者标记整理算法。
7. ⭐常见的垃圾回收器有哪些?重点CMS、G1
- 新生代收集器:Serial、ParNew、Parallel Scavenge;
- 老年代收集器:Serial Old、Parallel Old、CMS;
- 整堆收集器:G1;
搭配使用:Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Serial Old、Parallel Scavenge/Parallel Old、G1,Serial Old作为CMS出现“Concurrent Mode Failure”失败的后备预案。
JDK 默认垃圾收集器(使用 java -XX:+PrintCommandLineFlags -version
命令查看)
**Serial收集器:**单线程收集器, “Stop The World”垃圾收集时必须暂停工作线程,针对新生代,采用复制算法。
应用场景:HotSpot在Client模式下默认的新生代收集器。
优点:简单高效,单线程下性能较好。缺点:会导致较长的停顿时间,影响用户体验,不适合多线程场景。
**ParNew收集器:**Serial收集器的多线程版本,除多线程以外的行为、特点和Serial收集器一样。新生代复制算法。
应用场景:Server模式下的重要收集器。只有Serial和ParNew可以与CMS配合,因为Parallel Scavenge和G1都没有用传统的GC收集器代码框架而是另外独立实现。
优点:利用多线程提高了垃圾回收效率。缺点:在单核环境下性能不如 Serial 收集器。
Parallel Scavenge收集器:关注吞吐量,多线程并行。新生代复制算法。
特点:
- 注重吞吐量:单位时间内完成尽可能多的垃圾回收工作,减少垃圾回收时间,让用户代码获得更长运行时间。
- 用户可自行调整参数达到最合适的停顿时间或最大吞吐量,或者可以启动自适应调节策略:可根据系统运行情况自动调整一些参数,达到更好的性能表现。
-XX:UseAdaptiveSizePolicy
开启。
优点:有效提高吞吐量。缺点:停顿时间可能较长。
Serial Old 收集器:Serial 收集器的老年代版本。单线程,老年代,标记 - 整理算法。
应用场景:主要是Client模式。Server模式下两大用途:用途1是jdk1.5及以前与Parallel Scavenge 收集器搭配使用。用途2是作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。
Parallel Old 收集器:多线程,是 Parallel Scavenge 收集器的老年代的版本。标记 - 整理算法。
CMS收集器:Concurrent Mark Sweep
并发标记清理。以获取最短回收停顿时间为目标,并发收集,需要更多的内存。侧重老年代,回收算法是标记-清除算法。HotSpot虚拟机第一款真正意义的并发收集器,第一次实现了让垃圾收集线程与用户线程同时工作。
优点:停顿时间短,适合对响应时间要求高的应用。缺点:会产生内存碎片,可能导致 Concurrent Mode Failure。
CMS运作过程:
- 初始标记
CMS initial mark
:仅标记一下GC Roots能直接关联到的对象;速度很快;但需要"Stop The World"; - 并发标记
CMS concurrent mark
:进行完整的GC Roots Tracing的过程;应用程序也在运行; - 重新标记
CMS remark
:为了修正并发标记期间因用户程序继续运作而导致标记变动的那一部分对象的标记记录; 需要"Stop The World",且停顿时间比初始标记稍长,但远比并发标记短;采用多线程并行执行来提升效率; - 并发清除
CMS concurrent sweep
:回收所有的垃圾对象;整个过程中耗时最长的并发标记和并发清除都可以与用户线程一起工作; 所以总体上说,CMS收集器的内存回收过程与用户线程一起并发执行;
缺点:
-
对CPU资源非常敏感。并发时收集线程占用一部分CPU资源。
-
无法处理浮动垃圾,可能出现"Concurrent Mode Failure"。
并发清除时,用户线程新产生的垃圾称为浮动垃圾。导致并发清除时需要预留内存空间,不能像其他收集器在老年代几乎填满时在进行收集。如果CMS预留的内存空间无法满足程序需要,会产生Concurrent Mode Failure,此时JVM启用后备预案:临时启用Serial Old收集器,
-
**产生大量内存碎片。**CMS基于标记清除算法,清除后不压缩。大量不连续的内存碎片会导致分配大内存对象时,由于无法找到足够的连续内存,需要提前触发一次Full GC。解决方法:
-XX:+UseCMSCompactAtFullCollection
使得出现上述情况时不Full GC而是进行内存碎片整理,但是整理过程无法并发会导致停顿时间变长。-XX:+CMSFullGCsBeforeCompaction
执行n次不压缩的Full GC后再来一次压缩整理。 -
由于空间不连续,CMS分配内存时采用空闲列表法,比简单的碰撞指针法消耗大。
CMS 垃圾回收器在 Java 9 中已经被标记为过时(deprecated),并在 Java 14 中被移除。
G1收集器:Garbage-First
将内存划分为多个 Region,同时兼顾新生代和老年代的回收。
特点:
- 可预测的停顿:降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒。
- 分代收集:能独立管理整个GC堆(新生代和老年代)而不需要与其他收集器搭配。虽然保留分代概念,但Java堆的内存布局有很大差别,将整个堆划分为多个大小相等的独立区域(Region),新生代和老年代不再是物理隔离,它们都是一部分Region(不需要连续)的集合。
- 空间整合:G1 从整体来看是基于“标记-整理”算法实现的收集器;从局部上(两个Region间)来看是基于“标记-复制”算法实现的。
- 并行与并发:能充分利用多CPU、多核环境下的硬件优势,使用多个CPU并行来缩短"Stop The World"停顿时间,可以并发让垃圾收集与用户程序同步进行。
应用场景:适用于需要低GC延迟停顿,具有大堆的应用。
面向服务端应用,针对具有大内存、多处理器的机器。为需要低GC延迟,并具有大堆的应用程序提供解决方案。**在堆大小约6GB或更大时,可预测的暂停时间可以低于0.5秒。**在下面的情况时,使用G1可能比CMS好:超过50%的Java堆被活动数据占用、对象分配频率或年代提升频率变化很大、GC停顿时间过长(长于0.5至1秒)。
G1收集器运作过程:
- 初始标记:短暂停顿。标记从 GC Roots 可直接引用的对象。修改TAMS(Next Top at Mark Start),让下一阶段并发运行时,用户程序能在正确可用的Region中创建新对象。
- 并发标记:与应用并发运行,标记所有可达对象。 这一阶段可能持续较长时间,取决于堆的大小和对象的数量。
- 最终标记:短暂停顿,处理并发标记阶段结束后残留的少量未处理的引用变更。
- 筛选回收:排序各个Region的回收价值和成本,然后根据用户期望的GC停顿时间来制定回收计划,按计划回收一些价值高的Region中垃圾对象。回收时采用"复制"算法,从一个或多个Region复制存活对象到堆上的另一个空的Region,并且在此过程中压缩和释放内存。
从 JDK9 开始,G1 垃圾收集器成为了默认的垃圾收集器。
ZGC收集器 低延迟、支持TB级内存
标记-复制算法。
ZGC 可以将暂停时间控制在几毫秒以内,且暂停时间不受堆内存大小的影响,出现 Stop The World 的情况会更少,但代价是牺牲了一些吞吐量。ZGC 最大支持 16TB 的堆内存。
ZGC 在 Java11 中引入,处于试验阶段。经过多个版本的迭代,不断的完善和修复问题,ZGC 在 Java15 已经可以正式使用了。不过,默认的垃圾回收器依然是 G1。
jvm垃圾回收之垃圾收集器 - 隐风 - 博客园
JVM垃圾回收详解(重点) | JavaGuide
类加载器
1. java类文件结构是什么?
- class 文件是一串连续的二进制,由 0 和 1 组成,但我们仍然可以借助一些工具来看清楚它的真面目。
- class 文件的内容通常可以分为下面这几部分,魔数、版本号、常量池、访问标记、类索引、父类索引、接口索引、字段表、方法表、属性表。
- 魔数:确定当前文件是否为能被虚拟机接收的Class文件,Java 规范规定魔数为固定值:
0xCAFEBABE
。 - 文件版本号:minor次版本号,major主版本号。
- 常量池:存放字面量、符号引用。常量池计数器从1开始,索引值为0表示不引用任何一个常量池项,每个常量池项都是一个表(表的第一位是标志位,后面是信息数组)。字面量例如文本字符串、声明为final的常量值。符号引用包括:类和接口的全限定名、字段名称和描述符、方法名称和描述符。
javap -v class类名
指令来可查看class文件常量池信息。 - 访问标记用于识别类或接口的访问信息,比如说是不是 public | private | protected,是不是 static,是不是 final 等。
- 类索引、父类索引和接口索引用来确定类的继承关系。
- 字段表用来存储字段的信息,包括字段名,字段的参数,字段的签名。
- 方法表用来存储方法的信息,包括方法名,方法的参数,方法的签名。
- 属性表用来存储属性的信息,包括字段的初始值,方法的字节码指令等。
ClassFile {u4 magic; //Class 文件的标志u2 minor_version;//Class 的小版本号u2 major_version;//Class 的大版本号u2 constant_pool_count;//常量池的数量cp_info constant_pool[constant_pool_count-1];//常量池u2 access_flags;//Class 的访问标记u2 this_class;//当前类u2 super_class;//父类u2 interfaces_count;//接口数量u2 interfaces[interfaces_count];//一个类可以实现多个接口u2 fields_count;//字段数量field_info fields[fields_count];//一个类可以有多个字段u2 methods_count;//方法数量method_info methods[methods_count];//一个类可以有个多个方法u2 attributes_count;//此类的属性表中的属性数attribute_info attributes[attributes_count];//属性表集合
}
2. ⭐java类的生命周期?
java类的生命周期有 7 个阶段:
加载(Loading)、
验证(Verification)、准备(Preparation)、解析(Resolution)、
初始化(Initialization)、
使用(Using)和卸载(Unloading)。
其中,验证、准备和解析这三个阶段可以统称为连接(Linking)。
说说java类的加载过程?
- 类加载过程:加载->连接->初始化。
- 连接过程又可分为三步:验证->准备->解析。
主要包括加载、验证、准备、解析和初始化这几个阶段。加载阶段将字节码文件读入内存并创建 Class 对象;验证阶段确保字节码的正确性;准备阶段为类的静态变量分配内存并设置初始值;解析阶段将符号引用转换为直接引用;初始化阶段执行类的静态代码块等初始化操作。
**加载:**通过全类名获取定义这个类的二进制字节流,把字节流中的静态存储结构转换为内存方法区的运行时数据,在内存中生成代表这个类的Class
对象来作为方法区类数据的访问入口。由双亲委派模型决定使用哪个类加载器完成此过程。
加载阶段与下面的连接阶段可能一部分时间重叠,如一部分字节码文件格式验证动作
**验证:**验证格式、语义等。确保 Class 文件的字节流中包含的信息符合《Java 虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。
- 文件格式验证。Class 文件格式检查。基于该类的二进制字节流进行,其余三个验证阶段都是基于方法区的存储结构上进行的,不会再直接读取、操作字节流。
- 元数据验证。分析字节码语义,符合java语言规范
- 字节码验证。分析数据流和控制流,确保程序语义合法、符合逻辑
- 符号引用验证。类的正确性检查。
准备:正式为类变量分配内存并设置类变量初始零值。
从概念上讲,类变量所使用的内存都应当在 方法区 中进行分配。不过有一点需要注意的是:JDK 7 之前,HotSpot 使用永久代来实现方法区的时候,实现是完全符合这种逻辑概念的。 而在 JDK 7 及之后,HotSpot 已经把原本放在永久代的字符串常量池、静态变量等移动到堆中,这个时候类变量则会随着 Class 对象一起存放在 Java 堆中。
解析:虚拟机将常量池内的符号引用替换为直接引用。主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符 7 类符号引用进行。
**初始化:**执行初始化方法 ()方法。<clinit> ()
方法是编译之后自动生成的。注意只有主动去使用类时才会初始化类。
静态代码块在类加载时最先执行,且只执行一次。父类的静态代码块先于子类的静态代码块。
创建实例时,初始化普通属性值和普通代码块自上而下进行,构造方法在实例创建过程中最后执行。
- 遇到
new
程序创建一个类的实例对象、getstatic
访问类的静态变量(不是静态常量,常量会被加载到运行时常量池)、putstatic
给类的静态变量赋值 、invokestatic
调用类的静态方法,这 4 条字节码指令时 - 使用
java.lang.reflect
包的方法对类进行反射调用时如Class.forName("...")
,newInstance()
等等。如果类没初始化,需要触发其初始化。 - 初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。
- 虚拟机启动时,用户需要定义一个要执行的主类 (包含
main
方法的那个类),虚拟机会先初始化这个类。
使用
类卸载:类的Class对象被垃圾回收,包括:Class不被引用、实例对象被回收、类加载器被回收。
由 jvm 自带的类加载器加载的类是不会被卸载的,但是由我们自定义的类加载器加载的类是可能被卸载的。
JDK 自带的 BootstrapClassLoader
, ExtClassLoader
, AppClassLoader
负责加载 JDK 提供的类,所以它们(类加载器的实例)肯定不会被回收。
3. 类加载器的作用?
加载java类的字节码文件到jvm中。
每个java类都有一个引用指向加载它的ClassLoader,数组类是由JVM直接生成而非ClassLoader创建的。
静态代码块在类加载时最先执行,且只执行一次。父类的静态代码块先于子类的静态代码块。
创建实例时,初始化普通属性值和普通代码块自上而下进行,构造方法在实例创建过程中最后执行。
4. Java 中有哪些主要的类加载器?
启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader)。
启动类加载器负责加载核心类库,最顶层的加载类。%JAVA_HOME%/lib
下的 rt.jar
、resources.jar
、charsets.jar
等jar包和类 ,被 -Xbootclasspath
参数指定的路径下的所有类。通常表示为 null。
获取到
ClassLoader
为null
就是BootstrapClassLoader
加载的,因为BootstrapClassLoader
由 C++ 实现,在 Java 中没有与之对应的类。
扩展类加载器负责加载扩展目录下的类。%JRE_HOME%/lib/ext
下的jar包和类,java.ext.dirs
指定路径下的
应用程序类加载器负责加载应用程序的类。当前应用 classpath 下的所有 jar 包和类。
5. 自定义类加载器?
继承 ClassLoader
抽象类。关键方法loadClass和findClass。如果我们不想打破双亲委派模型,就重写 ClassLoader
类中的 findClass()
方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。但是,如果想打破双亲委派模型则需要重写 loadClass()
方法。
protected Class loadClass(String name, boolean resolve)
:加载指定二进制名称的类,实现了双亲委派机制 。name
为类的二进制名称,resolve
如果为 true,在加载时调用 resolveClass(Class<?> c)
方法解析该类。
protected Class findClass(String name)
:根据类的二进制名称来查找类,默认实现是空方法。
Tomcat 服务器自定义了类加载器
WebAppClassLoader
来打破双亲委托机制,实现 Web 应用之间的类隔离
6.⭐介绍双亲委派模型?
双亲委派模型是指当一个类加载器收到类加载请求时,它首先不会自己去尝试加载这个类,而是把请求委托给父类加载器去加载,依次向上委托,直到启动类加载器。只有当父类加载器无法加载该类时,子类加载器才会尝试自己去加载。
双亲委派模型的优点:避免重复的类加载,保证java核心API不被篡改,
类加载器之间的父子关系一般不是以继承的关系来实现的,通常使用组合关系来复用父加载器的代码。
loadClass执行流程:
- 判断当前类是否被加载过。加载过了的直接返回,否则尝试加载。
- 类加载器把请求委派给父类加载器,调用父类加载器的loadClass方法来加载类,最终所有请求传送到顶层的
BootstrapClassLoader
- 父类加载器反馈自己无法完成加载请求时,也就是搜索范围中没有找到所需的类,子加载器尝试自己
findClass()
加载 - 若子类加载器无法加载,抛出
ClassNotFoundException
JVM 判定两个 Java 类是否相同:不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。
相关文章:
面试题整理:Java虚拟机 JVM 内存区域、垃圾回收、类加载器
文章目录 JVM虚拟机内存区域1. ⭐JVM的内存区域有哪些?每个区域的作用是什么?2. 堆和栈的区别是什么?3. 堆内存是如何划分的?4. 永久代和元空间是什么关系?5. 对JVM常量池的理解?6. ⭐Java 对象的创建过程&…...
ASP.NET Core 使用 WebClient 从 URL 下载
本文使用 ASP .NET Core 3.1,但它在.NET 5、 .NET 6和.NET 8上也同样适用。如果使用较旧的.NET Framework,请参阅本文,不过,变化不大。 如果想要从 URL 下载任何数据类型,请参阅本文:HttpClient 使用WebC…...
第六届MathorCup高校数学建模挑战赛-A题:淡水养殖池塘水华发生及池水自净化研究
目录 摘要 1 问题的重述 2 问题的分析 2.1 问题一的分析 2.2 问题二的分析 2.3 问题三的分析 2.4 问题四的分析 2.5 问题五的分析 3. 问题的假设 4. 符号说明 5. 模型的建立与求解 5.1 问题一的建模与求解 5.1.1 分析对象与指标的选取 5.1.2 折线图分析 5.1.3 相关性分析 5.1.4…...
GnuTLS: 在 pull 函数中出错。 无法建立 SSL 连接。
提示信息 [root@localhost ~]# wget https://download.docker.com/linux/static/stable/x86_64/docker-27.5.1.tgz --2025-02-06 12:45:34-- https://download.docker.com/linux/static/stable/x86_64/docker-27.5.1.tgz 正在解析主机 download.docker.com (download.docker.…...
OpenAI 实战进阶教程 - 第十二节 : 多模态任务开发(文本、图像、音频)
适用读者与目标 适用读者:已经熟悉基础的 OpenAI API 调用方式,对文本生成或数据处理有一定经验的计算机从业人员。目标:在本节中,你将学会如何使用 OpenAI 提供的多模态接口(图像生成、语音转录等)开发更…...
《qt easy3d中添加孔洞填充》
《qt easy3d中添加孔洞填充》 效果展示一、创建流程二、核心代码效果展示 参考链接Easy3D开发——点云孔洞填充 一、创建流程 创建动作,并转到槽函数,并将动作放置菜单栏,可以参考前文 其中,槽函数on_actionHoleFill_triggered实现如下:...
windows蓝牙驱动开发-蓝牙常见问题解答
Windows 可以支持多少个蓝牙无线电? Windows 中的蓝牙堆栈仅支持一个蓝牙无线电。 此无线电必须符合蓝牙规范和最新的 Windows 硬件认证计划要求。 蓝牙和 Wi-Fi 无线电如何有效共存? 蓝牙和 Wi-Fi 无线电都在 2.4 GHz 频率范围内运行,因此…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_ssl_version 函数
定义 event\ngx_event_openssl.h 中: #if (OPENSSL_VERSION_NUMBER > 0x10100001L)#define ngx_ssl_version() OpenSSL_version(OPENSSL_VERSION)#else#define ngx_ssl_version() SSLeay_version(SSLEAY_VERSION)#endif #if (OPENSSL_VERSION_NUMBER…...
提示工程:少样本提示(Few-shot Prompting)
少样本提示(Few-shot Prompting)是一种利用大语言模型从少量示例样本中学习并处理任务的方法。它的核心思想是利用大语言模型的上下文学习能力,通过在提示中增加“示例样本”来启发大语言模型达到举一反三的效果。这种方法避免了重新训练或者…...
从量化投资到AI大模型:DeepSeek创始人梁文锋的创新之路
一、学术的启蒙:学霸的崭露头角 梁文锋的成长故事始于1985年,他出生在广东省湛江市的一个普通家庭。从小,梁文锋就展现出对知识的强烈渴望和非凡的学习能力,尤其在数学领域,他总是能够轻松解决复杂的难题,成为学校里备受瞩目的“学霸”。 2002年,年仅17岁的梁文锋以吴川…...
基于lstm+gru+transformer的电池寿命预测健康状态预测-完整数据代码
项目视频讲解: 毕业设计:基于lstm+gru+transformer的电池寿命预测 健康状态预测_哔哩哔哩_bilibili 数据: 实验结果:...
物品匹配问题-25寒假牛客C
登录—专业IT笔试面试备考平台_牛客网 这道题看似是在考察位运算,实则考察的是n个物品,每个物品有ai个,最多能够得到多少个物品的配对.观察题目可以得到,只有100,111,010,001(第一位是ci,第二位是ai,第三位是bi)需要进行操作,其它都是已经满足条件的对,可以假设对其中两个不同…...
Pyecharts系列课程05——散点图(Scatter)
本章我们学习Pyecharts中散点图的实现方法,散点图通常用于观察数据的分布和相关性。 1. 基础使用 散点图也是数据直角坐标系,与我们之前的直方图、折线图的基本用法是一致的。 示例: from pyecharts.charts import Scatterx_data [1, 2, …...
c/c++蓝桥杯经典编程题100道(18)括号匹配
括号匹配 ->返回c/c蓝桥杯经典编程题100道-目录 目录 括号匹配 一、题型解释 二、例题问题描述 三、C语言实现 解法1:栈匹配法(难度★) 解法2:计数器法(仅限单一括号类型,难度★☆) …...
C++病毒
免费版请关注作者,私信 第一期 声明: 仅供损害电脑,不得用于非法。 直接上代码 #include <bits/stdc.h> #include <windows.h> using namespace std; HHOOK g_hHook; LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LP…...
vue学习4
1.自定义创建项目 2.ESlint代码规范 正规的团队需要统一的编码风格 JavaScript Standard Style 规范说明:https://standardjs.com/rules-zhcn.html 规则中的一部分: (1)字符串使用单引号 ‘aabc’ (2)无分号 const name ‘zs’ (3)关键字后加空格 if(n…...
解锁 DeepSeek 模型高效部署密码:蓝耘平台深度剖析与实战应用
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
《DEADiff:一种具有解耦表示高效的风格化扩散模型》
paper:2403.06951 GitHub:bytedance/DEADiff: [CVPR 2024] Official implementation of "DEADiff: An Efficient Stylization Diffusion Model with Disentangled Representations" 目录 摘要 1、介绍 2、相关工作 2.1 扩散模型在文本到…...
webpack系统学习
webpack4和webpack5区别1---loader_webpack4与webpack5处理图片的不同-CSDN博客 webpack4和webpack5区别2---代码压缩_webpack4如何使用terser-CSDN博客 webpack4和webpack5区别3---缓存_cacheprune-CSDN博客 webpack4和webpack5区别4---自动清除打包目录_webpack4打包目录清…...
C++11新特性之unique_ptr智能指针
本节继续介绍智能指针,不了解的读者可以先阅读——C11新特性之shared_ptr智能指针-CSDN博客 1.介绍 unique_ptr是C11标准提供的另一种智能指针。与shared_ptr不同的是,unique_ptr指针指向的堆内存无法同其他unique_ptr共享,也就是每一片堆内…...
如何使用python制作一个天气预报系统
制作一个天气预报系统可以通过调用天气 API 来获取实时天气数据,并使用 Python 处理和展示这些数据。以下是一个完整的指南,包括代码实现和注意事项。 1. 选择天气 API 首先,需要选择一个提供天气数据的 API。常见的天气 API 有: OpenWeatherMap API:提供全球范围内的天…...
保姆级教程Docker部署Zookeeper模式的Kafka镜像
目录 一、安装Docker及可视化工具 二、Docker部署Zookeeper 三、单节点部署 1、创建挂载目录 2、运行Kafka容器 3、Compose运行Kafka容器 4、查看Kafka运行状态 5、验证生产消费 四、部署可视化工具 1、创建挂载目录 2、Compose运行Kafka-eagle容器 3、查看Kafka-e…...
在阿里云ECS上一键部署DeepSeek-R1
DeepSeek-R1 是一款开源模型,也提供了 API(接口)调用方式。据 DeepSeek介绍,DeepSeek-R1 后训练阶段大规模使用了强化学习技术,在只有极少标注数据的情况下提升了模型推理能力,该模型性能对标 OpenAl o1 正式版。DeepSeek-R1 推出…...
P3413 SAC#1 - 萌数
题目背景 本题由世界上最蒟蒻的 SOL 提供。 寂月城网站是完美信息教室的官网。地址:http://191.101.11.174/mgzd。 题目描述 蒟蒻 SOL 居然觉得数很萌! 好在在他眼里,并不是所有数都是萌的。只有满足“存在长度至少为 22 的回文子串”的数是萌的——也就是说,101 是萌…...
DeepSeek-R1系列01——技术报告解读:DeepSeek-R1:通过强化学习激励 LLM 中的推理能力
1.阅读目标 DeepSeek-R1 发布,性能对标 OpenAI o1 正式版 DeepSeek-R1已经发布,并同步开源模型权重。 DeepSeek-R1 遵循 MIT License,允许用户通过蒸馏技术借助 R1 训练其他模型。 DeepSeek-R1 上线API,对用户开放思维链输出&a…...
(1/100)每日小游戏平台系列
每日小游戏平台 项目简介以及地址 准备开发一个一百天小游戏平台,使用Flask构建的简单游戏导航网站,无需登录,让大家在返工的同时也可以愉快的摸鱼玩耍。 每天更新一个小游戏上传,看看能不能坚持一百天。 这些小游戏主要使用前端…...
前端布局与交互实现技巧
前端布局与交互实现技巧 1. 保持盒子在中间位置 在网页设计中,经常需要将某个元素居中显示。以下是一种常见的实现方式: HTML 结构 <!doctype html> <html lang"en"> <head><meta charset"UTF-8"><m…...
spark单机版本搭建
spark单机版本搭建 服务器配置 CPU内存磁盘操作系统内核版本2c2g40GCentOS 73.10.0 1.JDK 下载安装 # 列出版本 yum -y list java* # 安装 yum -y install java-1.8.0-openjdk java-1.8.0-openjdk-devel # 检查 java -version2.spark下载 spark下载地址 本文下载&#x…...
【C++八股】std::atomic —— 原子操作
std::atomic 是 C11 引入的模板类,主要用于多线程编程中的原子操作,确保在多个线程访问或修改共享变量时不会产生数据竞争。 1. std::atomic 的作用 在多线程环境下,普通变量的操作不是原子的,可能被多个线程同时访问和修改&…...
GPU、CUDA 和 cuDNN 学习研究【笔记】
分享自己在入门显存优化时看过的一些关于 GPU 和 CUDA 和 cuDNN 的网络资料。 更多内容见: Ubuntu 22.04 LTS 安装 PyTorch CUDA 深度学习环境-CSDN博客CUDA 计算平台 & CUDA 兼容性【笔记】-CSDN博客 文章目录 GPUCUDACUDA Toolkit都包含什么?NVID…...
AI-学习路线图-PyTorch-我是土堆
1 需求 PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】_哔哩哔哩_bilibili PyTorch 深度学习快速入门教程 配套资源 链接 视频教程 https://www.bilibili.com/video/BV1hE411t7RN/ 文字教程 https://blog.csdn.net/xiaotudui…...
Android Camera API 介绍
一 StreamConfigurationMap 1. StreamConfigurationMap 的作用 StreamConfigurationMap 是 Android Camera2 API 中的一个核心类,用于描述相机设备支持的输出流配置,包含以下信息: 支持的格式与分辨率:例如 YUV_420_888、JPEG、…...
活动预告 |【Part 1】Microsoft 安全在线技术公开课:通过扩展检测和响应抵御威胁
课程介绍 通过 Microsoft Learn 免费参加 Microsoft 安全在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft Cloud 技术的了解。参加我们举办的“通过扩展检测和响应抵御威胁”技术公开课活动,了解如何更好地在 Microsoft 365 Defen…...
RabbitMQ 消息顺序性保证
方式一:Consumer设置exclusive 注意条件 作用于basic.consume不支持quorum queue 当同时有A、B两个消费者调用basic.consume方法消费,并将exclusive设置为true时,第二个消费者会抛出异常: com.rabbitmq.client.AlreadyClosedEx…...
web第二次作业
一.后台管理系统首页代码 1.html代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>实验&l…...
AI 编程开发插件codeium Windsurf(vscode、editor) 安装
1、vscode中安装: 2、vscode中使用 3、输入注册的账号密码,就可以使用。 4、或者直接下载editor 5、安装editor 下一步,下一步,直到安装成功,中间可以改下安装位置,如果C盘空间不够。 同样提示注册或者登录…...
变压器-000000
最近一个项目是木田12V的充电器,要设计变压器,输出是12V,电压大于1.5A12.6*1.518.9W. 也就是可以将变压器当成初级输入的一个负载。输入端18.9W. 那么功率UI 。因为变压器的输入是线性上升的,所以电压为二份之一,也就是1/2*功率…...
C# OpenCvSharp 部署MOWA:多合一图像扭曲模型
目录 说明 效果 项目 代码 下载 参考 C# OpenCvSharp 部署MOWA:多合一图像扭曲模型 说明 算法模型的paper名称是《MOWA: Multiple-in-One Image Warping Model》 ariv链接 https://arxiv.org/pdf/2404.10716 效果 Stitched Image 翻译成中文意思是&…...
Ai无限免费生成高质量ppt教程(deepseek+kimi)
第一步:打开deepseek官网(DeepSeek) 1.如果deepseek官网网络繁忙,解决方案如下: (1)使用easychat官网(EasyChat)使用deepseek模型,如图所示: (2)本地部署&…...
LLMs之DeepSeek r1:Logic-RL的简介、安装和使用方法、案例应用之详细攻略
LLMs之DeepSeek r1:Logic-RL的简介、安装和使用方法、案例应用之详细攻略 目录 Logic-RL的简介 1、Logic-RL的特点 2、性能 Logic-RL 的安装和使用方法 1、安装 2、使用方法 数据准备 基础模型 指令模型 训练执行 实现细节 Logic-RL的案例应用 Logic-RL…...
解决跨域问题
相信大多数的伙伴在第一次通过vue spring 做项目的时候都会遇到这个问题 什么是同源策略和跨域问题 同源策略指的就是,浏览器出于安全考虑,实施的一种策略,即只允许来自同一源(即协议域名端口都相同)的请求访问资源. 否则就会导致跨域问题 例如: http://xxx.com -> http…...
网络工程师 (28)IEEE802标准
前言 IEEE 802标准是由电气和电子工程师协会(IEEE)制定的一组局域网(LAN)和城域网(MAN)标准,定义了网络中的物理层和数据链路层。 一、起源与背景 IEEE 802又称为LMSC(LAN/MAN Stand…...
Playwright 与 Selenium 的关系
Playwright 与 Selenium 的关系 Playwright 和 Selenium 都是流行的浏览器自动化测试工具,它们都可以用于 Web 应用的端到端测试,但它们在设计理念、架构和功能上存在一些差异。 以下是两者的主要关系对比: 特性PlaywrightSelenium开发语言JavaScript (Node.js)多种语言 (…...
保研考研机试攻略:python笔记(4)
🐨🐨🐨15各类查找 🐼🐼二分法 在我们写程序之前,我们要定义好边界,主要是考虑区间边界的闭开问题。 🐶1、左闭右闭 # 左闭右闭 def search(li, target): h = len(li) - 1l = 0#因为都是闭区间,h和l都可以取到并且相等while h >= l:mid = l + (h - l) // 2…...
Matplotlib基础01( 基本绘图函数/多图布局/图形嵌套/绘图属性)
Matplotlib基础 Matplotlib是一个用于绘制静态、动态和交互式图表的Python库,广泛应用于数据可视化领域。它是Python中最常用的绘图库之一,提供了多种功能,可以生成高质量的图表。 Matplotlib是数据分析、机器学习等领域数据可视化的重要工…...
Spring Boot: 使用 @Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ
Spring Boot: 使用 Transactional 和 TransactionSynchronization 在事务提交后发送消息到 MQ 在微服务架构中,确保消息的可靠性和一致性非常重要,尤其是在涉及到分布式事务的场景中。本文将演示如何使用 Spring Boot 的事务机制和 TransactionSynchron…...
解析3DMAX转OBJ
3ds Max 是一款功能强大的三维建模、动画和渲染软件,而 OBJ 是一种常用的三维模型文件格式,以下是关于 3ds Max 转 OBJ 的相关解析: 3ds Max 转 OBJ 的原因 兼容性需求: OBJ 格式被众多三维软件和渲染器所支持,将 3…...
html为<td>添加标注文本
样式说明: /*为td添加相对定位点*/ .td_text {position: relative; }/*为p添加绝对坐标(相对于父元素中的定位点)*/ .td_text p {position: absolute;top: 80%;font-size: 8px; }参考资料:...
AI驱动的智能流程自动化是什么
在当今快速发展的数字化时代,企业正在寻找更高效、更智能的方式来管理日常运营和复杂任务。其中,“AI驱动的智能流程自动化”(Intelligent Process Automation, IPA)成为了一个热门趋势。通过结合人工智能(AIÿ…...
vue动态table 动态表头数据+动态列表数据
效果图: <template><div style"padding: 20px"><el-scrollbar><div class"scrollbar-flex-content"><div class"opt-search"><div style"width: 100px"> </div><div class"opt-b…...