JVM面试知识点1
内存结构(掌握内存结构划分、熟知各区域结构功能)
经典的JVM内存结构:
按照线程是否共享来划分:
Heap (堆区)
1. 堆区的介绍
堆是 OOM 故障最主要的发生区域。它是内存区域中最大的一块区域,被所有线程共享。存放的是实例化的对象信息;
Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC 堆”。
还可以细分为:新生代和老年代。再细致一点的有 Eden 空间、From Survivor 空间、To Survivor 空间等。
2. 堆区的调整
Java 堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以在运行时动态地调整。
通过设置如下参数,可以设定堆区的初始值和最大值,比如 -Xms256M -Xmx 1024M,其中 -X 这个字母代表它是 JVM 运行时参数,ms 是 memory start 的简称,中文意思就是内存初始值,mx 是 memory max 的简称,意思就是最大内存。
3. 堆的默认空间分配
创建一个新对象内存分配流程
Metaspace 元空间
在 HotSpot JVM 中,永久代( ≈ 方法区)中用于存放类和方法的元数据以及常量池,比如 Class 和 Method。每当一个类初次被加载的时候,它的元数据都会放到永久代中。
Java 8 时,类元信息、字段、静态属性、方法、常量等都移动到元空间区。比如 java/lang/Object 类元信息、静态属性 System.out、整形常量 100000 等。
元空间的本质和永久代类似,都是对 JVM 规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。
Java 虚拟机栈
对于每一个线程,JVM 都会在线程被创建的时候,创建一个单独的栈。也就是说虚拟机栈的生命周期和线程是一致,并且是线程私有的。除了 Native 方法以外,Java 方法都是通过 Java 虚拟机栈来实现调用和执行过程的。
所以 Java 虚拟机栈是虚拟机执行引擎的核心之一。而 Java 虚拟机栈中出栈入栈的元素就称为「栈帧」。
栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。
栈对应线程,栈帧对应方法
本地方法栈
本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。
程序计数器
程序计数器(Program Counter Register)是一块较小的内存空间。是线程私有的。
程序计数器用来存放执行指令的偏移量和行号指示器等,线程执行或恢复都要依赖程序计数器。此区域也不会发生内存溢出异常。
垃圾回收机制(掌握垃圾判定的逻辑以及常见判定方法、掌握常见的垃圾回收算法、并熟知其回收线程)
1.背景:
一般来讲,在我们编程的过程中是会不断的往内存中写入数据的,而这些数据用完了要及时从内存中清理,否则会引发OutOfMemory(内存溢出) ,所以每个编程者都必须遵从这一原则。
Java比较好,因为JVM存在GC机制,也就是说JVM会帮我们自动清理垃圾
2. 两种回收机制
2.1 引用计数
什么是引用计数呢?打个比方A a = new A(),代码中 A 对象被引用 a 所持有,此时引用计数就会 +1 ,如果 a 将引用置为 null 即a = null此时对象 A 的引用计数就会变为 0 ,GC算法检测到 A 对象引用计数为 0 就会将其回收。
优点:执行效率高;缺点:无法解决互相引用问题;
2.2 可达性分析
在JVM中,会将一些特殊的引用作为 GcRoot ,如果通过 GcRoot 可以访达的对象不会被当作垃圾对象。换种方式说就是,一个对象被 GcRoot 直接 或 间接持有,那么该对象就不会被当作垃圾对象。用一张图表示大概就是这个样子:
优点:解决了引用计数法的互相引用问题;
图中A、B、C、D可以被 GcRoot 访达,所以不会被回收。E、F不能被 GcRoot 访达,所以会被标记为垃圾对象。最典型的是G、H,虽说相互引用,但不能被 GcRoot 访达,所以也会被标记为垃圾对象。综上所述: 可达性分析 可以解决 引用计数 中 对象相互引用 不能被回收的问题。
什么类型的引用可作为 GcRoot 呢。 大概有如下四种:
- 栈中局部变量
- 方法区中静态变量
- 方法区中常量
- 本地方法栈JNI的引用对象
3. 回收算法
3.1. 标记清除算法
获取所有的 GcRoot 遍历内存中所有的对象,如果可以被 GcRoot 就加个标记,剩下所有的对象都将视为垃圾被清除。
- 优点:实现简单,执行效率高
- 缺点:容易产生 内存碎片(可用内存分布比较分散),如果需要申请大块连续内存可能会频繁触发 GC
3.2. 复制算法
将内存分为两块,每次只是用其中一块。首先遍历所有对象,将可用对象复制到另一块内存中,此时上一块内存可视为全是垃圾,清理后将新内存块置为当前可用。如此反复进行
- 优点:解决了内存碎片的问题
- 缺点:需要按顺序分配内存,可用内存变为原来的一半。
3.3. 标记压缩算法
获取所有的 GcRoot , GcRoot 开始从遍历内存中所有的对象,将可用对象压缩到另一端,再将垃圾对象清除。实则是牺牲时间复杂度来降低空间复杂度
- 优点:解决了标记清除的 内存碎片 ,也不需要复制算法中的 内存分块
- 缺点:仍需要将对象进行移动,执行效率略低。
4. 分代回收策略
在JVM中 垃圾回收器 是很繁忙的,如果一个对象存活时间较长,避免重复 创建/回收 给 垃圾回收器 进一步造成负担。
JVM制定了 分代回收策略 为每个对象设置生命周期 ,堆内存会划分不同的区域,来存储各生命周期的对象。一般情况下对象的生命周期有 新生代、老年代、永久代(java 8已废弃)。
4.1. 新生代
新生代内存工作流程:
- 当一个对象刚被创建时会放到 Eden 区域,当 Eden 区域即将存满时做一次垃圾回收,将当前存活的对象复制到 SurvivorA ,随后将 Eden 清空
- 当Eden 下一次存满时,再做一次垃圾回收,先将存活对象复制到 SurvivorB ,再把 Eden 和 SurvivorA 所有对象进行回收,
- 当Eden 再一次存满时,再做一次垃圾回收,将存活对象复制到 SurvivorA,再把 Eden 和 SurvivorB对象进行回收。如此反复进行大概 15 次,将最终依旧存活的对象放入到老年代区域。
新生代工作流程与 复制算法 应用场景较为吻合,都是以复制为核心,所以会采用复制算法。
4.2. 老年代
当一个对象存活时间较久会被存入到 老年代 区域。 老年代 区即将被存满时会做一次垃圾回收。
所以 老年代 区域特点是存活对象多、垃圾对象少,采用标记压缩 算法时移动少、也不会产生内存碎片。所以老年代 区域可以选用 标记压缩 算法进一步提升效率。
5. 四大引用
JVM为我们提供了四种对象引用方式:强引用、软引用、弱引用、虚引用 供我们选择,下面我用一张表格来做一下类比。
类的加载流程:(使用自己的理解进行阐述)
一、引言
当程序使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载、链接、初始化三个步骤对该类进行类加载。
二、类的加载、链接、初始化
1、加载
类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class对象。类的加载过程是由类加载器来完成,类加载器由JVM提供。我们开发人员也可以通过继承ClassLoader来实现自己的类加载器。
1.1、加载的class来源
- 从本地文件系统内加载class文件
- 从JAR包加载class文件
- 通过网络加载class文件
- 把一个java源文件动态编译,并执行加载。
2、类的链接
通过类的加载,内存中已经创建了一个Class对象。链接负责将二进制数据合并到 JRE中。链接需要通过验证、准备、解析三个阶段。
2.1、验证
验证阶段用于检查被加载的类是否有正确的内部结构,并和其他类协调一致。即是否满足java虚拟机的约束。
2.2、准备
类准备阶段负责为类的类变量分配内存,并设置默认初始值。
2.3、解析
解析阶段的目的,就是将这些符号引用解析为实际引用。如果符号引用指向一个未被加载的类,或者未被加载类的字段或方法,那么解析将触发这个类的加载(但未必会触发解析与初始化)。
简单来说就是通过类加载器加载当前类引用的其他对象;
3、类的初始化
类的初始化阶段,虚拟机主要对类变量进行初始化。虚拟机调用< clinit>方法,进行类变量的初始化。
java类中对类变量进行初始化的两种方式:
- 在定义时初始化
- 在静态初始化块内初始化
3.1、< clinit>方法相关
- 虚拟机会收集类及父类中的类变量及类方法组合为< clinit>方法,根据定义的顺序进行初始化。虚拟机会保证子类的< clinit>执行之前,父类的< clinit>方法先执行完毕。因此,虚拟机中第一个被执行完毕的< clinit>方法肯定是java.lang.Object方法。
- 如果类或者父类中都没有静态变量及方法,虚拟机不会为其生成< clinit>方法。
- 接口与类不同的是,执行接口的<clinit>方法不需要先执行父接口的<clinit>方法。 只有当父接口中定义的变量使用时,父接口才会初始化。 另外,接口的实现类在初始化时也一样不会执行接口的<clinit>方法。
- 虚拟机会保证一个类的< clinit>方法在多线程环境中被正确地加锁和同步,如果多个线程同时去初始化一个类,那么只有一个线程去执行这个类的< clinit>方法,其他线程都需要阻塞等待,直到活动线程执行< clinit>方法完毕。
3.2、类初始化时机
- 当虚拟机启动时,初始化用户指定的主类;
- 当遇到用以新建目标类实例的new指令时,初始化new指令的目标类;
- 当遇到调用静态方法或者使用静态变量,初始化静态变量或方法所在的类;
- 子类初始化过程会触发父类初始化;
- 如果一个接口定义了default方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口初始化;
- 使用反射API对某个类进行反射调用时,初始化这个类;
- Class.forName()会触发类的初始化
3.3、final定义的初始化
对于一个使用final定义的常量,如果在编译时就已经确定了值,在引用时不会触发初始化,因为在编译的时候就已经确定下来,就是“宏变量”。如果在编译时无法确定,在初次使用才会导致初始化。
如果final定义的变量在编译时无法确定,则在使用时还是会进行类的初始化。
3.4、ClassLoader只会对类进行加载,不会进行初始化
ClassLoader只会对类进行加载,不会进行初始化;使用Class.forName()会强制导致类的初始化。
三、类加载器
类加载器负责将.class文件(不管是jar,还是本地磁盘,还是网络获取等等)加载到内存中,并为之生成对应的java.lang.Class对象。一个类被加载到JVM中,就不会第二次加载了。
那怎么判断是同一个类呢?
每个类在JVM中使用全限定类名(包名+类名)与类加载器联合为唯一的ID,所以如果同一个类使用不同的类加载器,可以被加载到虚拟机,但彼此不兼容。
1、JVM类加载器分类
1.1、Bootstrap ClassLoader
Bootstrap ClassLoader为根类加载器,负责加载java的核心类库。根加载器不是ClassLoader的子类,是有 C++实现的。
根类加载器负责加载%JAVA_HOME%/jre/lib下的jar包(以及由虚拟机参数 -Xbootclasspath 指定的类)。
1.2 、Extension ClassLoader
Extension ClassLoader为扩展类加载器,负责加载%JAVA_HOME%/jre/ext或者java.ext.dirs系统熟悉指定的目录的jar包。大家可以将自己写的工具包放到这个目录下,可以方便自己使用。
1.3、 Appliaction ClassLoader
System ClassLoader为系统(应用)类加载器,负责加载加载来自java命令的-classpath选项、java.class.path系统属性,或者CLASSPATH环境变量所指定的JAR包和类路径。程序可以通过ClassLoader.getSystemClassLoader()来获取系统类加载器。如果没有特别指定,则用户自定义的类加载器默认都以系统类加载器作为父加载器。
1.4 自定义类加载器
四、类加载机制
1.1、JVM主要的类加载机制。
- 全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖和引用的其他Class也由该类加载器负责载入,除非显示使用另一个类加载器来载入。
- 父类委托(双亲委派):先让父加载器试图加载该Class,只有在父加载器无法加载时该类加载器才会尝试从自己的类路径中加载该类。
- 缓存机制:缓存机制会将已经加载的class缓存起来,当程序中需要使用某个Class时,类加载器先从缓存区中搜寻该Class,只有当缓存中不存在该Class时,系统才会读取该类的二进制数据,并将其转换为Class对象,存入缓存中。这就是为什么更改了class后,需要重启JVM才生效的原因。
五、创建并使用自定义类加载器
1、自定义类加载分析
除了根类加载器,所有类加载器都是ClassLoader的子类。所以我们可以通过继承ClassLoader来实现自己的类加载器。
ClassLoader类有两个关键的方法:
- protected Class loadClass(String name, boolean resolve):name为类名,resove如果为true,在加载时解析该类。
- protected Class findClass(String name) :根据指定类名来查找类。
所以,如果要实现自定义类,可以重写这两个方法来实现。但推荐重写findClass方法,而不是重写loadClass方法,因为loadClass方法内部回调用findClass方法。
loadClass加载方法流程:
- 判断此类是否已经加载;
- 如果父加载器不为null,则使用父加载器进行加载;反之,使用根加载器进行加载;
- 如果前面都没加载成功,则使用findClass方法进行加载。
所以,为了不影响类的加载过程,我们重写findClass方法即可简单方便的实现自定义类加载。
2、实现自定义类加载器
ClassLoader还有一个重要的方法defineClass(String name, byte[] b, int off, int len)。此方法的作用是将class的二进制数组转换为Calss对象。
垃圾回收器:
CMS垃圾回收的过程:
CMS(Concurrent Mark-Sweep)收集器是 Java 虚拟机中的一种老年代(Old Generation)垃圾收集器,它主要目标是减少垃圾收集时的应用程序停顿(STW)时间。
CMS 使用并发(Concurrent)的方式来执行垃圾收集,使用的是“标记-清理”算法,尽量减少在垃圾收集过程中应用程序的暂停时间。
CMS收集器整体流程
其执行过程分为初始标记、并发标记、重新标记和并发清理等过程
初始标记(预先标记):
只是标记GC Roots能直接关联到的对象,但需要“Stop The World”停顿,即在此期间暂停所有应用线程。(用于标记直接被GCRoot获取的对象,会造成stw);
并发标记:
从GC Roots出发标记上所有和GC Root相连的存活对象,不会stw;(用于标记在GC链路上的对象)
重新标记:
修正一下GC线程和用户线程同时跑时产生的错标和漏标;也需要stw,但是停顿时间较短;
并发清除:
GC线程会清除不再被引用的对象,并回收他们占用的内存空间。(多GC线程,用户线程和GC线程同时跑),不会stw;
G1 GC(垃圾优先收集器)是JDK 9以后的默认回收器
1.1、G1收集器的堆空间内存划分
在1.7之后,我们可以通过参数-XX:+UseG1GC装配它
堆中的内存区域被划为了一个个的Region区。
每个分区都可能是年轻代也可能是老年代,但是在同一时刻只能属于某个代。在运行时,每个分区都会被打上唯一的分区标识。 不过在G1收集器中,年轻代Eden区、幸存区Survivor、老年代Old区这些概念依旧还存在,但却成为了逻辑上的概念,这样做的好处在于:也可以复用之前分代框架的逻辑,同时也满足了Java对象朝生夕死的特性。
不过在HotSpot的源码TARGET_REGION_NUMBER定义了Region区的数量限制为2048个(实际上允许超过这个值,但是超过这个数量后,堆空间会变的难以管理)。
一般Region区的大小等于堆空间的总大小除以2048,比如目前的堆空间总大小为8GB,就是8192MB/2048=4MB,那么最终每个Region区的大小为4MB,当然也可以用参数-XX:G1HeapRegionSize强制指定每个Region区的大小,但是不推荐;
默认新生代对堆内存的初始占比是5%;可以通过-XX:G1NewSizePercent设置新生代初始占比。
最多新生代的占比不会超过堆空间总大小的60%,可以通过-XX:G1MaxNewSizePercent调整。
G1中的年老代晋升条件和之前的无差,达到年龄阈值的对象会被转入年老代的Region区中,不同的是对于大对象的分配,在G1中不会让大对象进入年老代,在G1中由专门存放大对象的Region区叫做Humongous区,如果在分配对象时,判定出一个对象属于大对象,那么则会直接将其放入Humongous区存储。
在G1中,判定一个对象是否为大对象的方式为:对象大小是否超过单个普通Region区的50%,如果超过则代表当前对象为大对象,那么该对象会被直接放入Humongous区。
当堆空间发生全局GC(FullGC)时,除开回收新生代和年老代之外,也会对Humongous区进行回收。
G1收集器具备如下特性:
● ①与CMS收集器一样,能够与用户线程同时执行,完成并发收集。
● ②GC过程会有整理内存的过程,不会产生内存碎片,并且整理空闲内存速度更快。
● ③GC发生时,停顿时间可控,可以让程序更大程度上追求低延迟。
● ④追求低延迟的同时,尽可能会保证高吞吐量。
● ⑤对于堆的未使用内存可以返还给操作系统。
1.2、G1收集器GC类型
G1中主要存在YoungGC、MixedGC以及FullGC三种GC类型,这三种GC类型分别会在不同情景下被触发。
1.2.1、YoungGC
所以YoungGC并非说Eden区放满了就会立马被触发,在G1中,当新生代区域被用完时,G1首先会大概计算一下回收当前的新生代空间需要花费多少时间,如果回收时间远远小于参数-XX:MaxGCPauseMills设定的值,那么不会触发YoungGC,而是会继续为新生代增加新的Region区用于存放新分配的对象实例。
1.2.2、MixedGC
当整个堆中年老代的区域占有率达到参数-XX:InitiatingHeapOccupancyPercent设定的值后触发MixedGC,发生该类型GC后,会回收所有新生代Region区、部分年老代Region区(会根据期望的GC停顿时间选择合适的年老代Region区优先回收)以及大对象Humongous区。
1.2.3、FullGC
当整个堆空间中的空闲Region不足以支撑拷贝对象或由于元数据空间满了等原因触发,在发生FullGC时,G1首先会停止系统所有用户线程,然后采用单线程进行标记、清理和压缩整理内存,以便于清理出足够多的空闲Region来供下一次MixedGC使用。但该过程是单线程串行收集的,因此这个过程非常耗时的(ShenandoahGC中采用了多线程并行收集)。
1.3、G1收集器垃圾回收过程
G1收集器一般在发生GC时执行过程大致会分为四个步骤(主要指MixedGC):
- ①初始标记(InitialMark):先触发STW,然后使用单条GC线程快速标记GCRoots直连的对象。
- ②并发标记(ConcurrentMarking):与CMS的并发标记过程一致,采用多条GC线程与用户线程共同执行,根据Root根节点标记所有对象。
- ③最终标记(Remark):同CMS的重新标记阶段,主要是为了纠正并发标记阶段因用户操作导致的错标、误标、漏标对象。
- ④筛选回收(Cleanup):先对各个Region区的回收价值和成本进行排序,找出「回收价值最大」的Region优先回收。
在G1中不管是新生代还是年老代,回收算法都是采用复制算法,在GC发生时都会将一个Region区中存活的对象复制到另外一个Region区内。同比之前的CMS收集器采用的标-清算法而言,这种方式不会造成内存碎片,因此也不需要花费额外的成本整理内存。
一款源自于JDK11的性能魔兽 - ZGC
它也是一款基于分区概念的内存布局GC器,这款GC器是真正意义上的不分代收集器,因为它无论是从逻辑上,还是物理上都不再保留分代的概念。
Java引入ZGC的目的主要有如下四点:
● ①奠定未来GC特性的基础。
● ②为了支持超大级别堆空间(TB级别),最高支持16TB。
● ③在最糟糕的情况下,对吞吐量的影响也不会降低超过15%。
● ④GC触发产生的停顿时间不会偏差10ms。
2.1、ZGC堆空间内存划分
在ZGC中,也会把堆空间划分为一个个的Region区域,但ZGC中的Region区不存在分代的概念,它仅仅只是简单的将所有Region区分为了大、中、小三个等级,如下:
- 小型区/页(Small):固定大小为2MB,用于分配小于256KB的对象。
- 中型区/页(Medium):固定大小为32MB,用于分配>=256KB ~ <=4MB的对象。
- 大型区/页(Large):没有固定大小,容量可以动态变化,但是大小必须为2MB的整数倍,专门用于存放>4MB的巨型对象。但值得一提的是:每个Large区只能存放一个大对象,也就代表着你的这个大对象多大,那么这个Large区就为多大,所以一般情况下,Large区的容量要小于Medium区,并且需要注意:Large区的空间是不会被重新分配的(稍后分析)。
2.2、ZGC回收过程
ZGC收集器在发生GC时,其实主要操作只有三个:标记、转移与重定位。
- 标记:从根节点出发标记所有存活对象。
- 转移:将需要回收区域中的存活对象转移到新的分区中。
- 重定位:将所有指向转移前地址的指针更改为指向转移后的地址。
ZGC中的一次垃圾回收过程会被分为十个步骤:初始标记、并发标记、再次标记、并发转移准备:[非强引用并发标记、重置转移集、回收无效页面(区)、选择目标回收页面、初始化转移集(表)]、初始转移、并发转移,其中只有初始标记、再次标记、初始转移阶段会存在短暂的STW,其他阶段都是并发执行的。
2.2.1、ZGC的核心 - 染色指针(colored pointers)技术
ZGC的核心技术之一,在此之前所有的GC信息保存在对象头中,但ZGC中的GC信息保存在指针内。
相关文章:
JVM面试知识点1
内存结构(掌握内存结构划分、熟知各区域结构功能) 经典的JVM内存结构: 按照线程是否共享来划分: Heap (堆区) 1. 堆区的介绍 堆是 OOM 故障最主要的发生区域。它是内存区域中最大的一块区域,被所有线程共…...
wordpress
2024年自己建网站的步骤,新手自学建站教程 – 奶爸建站笔记 超详细图解:从 0 搭建一个个人网站,也太简单了吧 - 王一白 - 博客园 如何使用插件或者自定义页面创建一个WordPress着陆页 - 闪电博...
Day33 动态规划part02
62.不同路径 本题大家掌握动态规划的方法就可以。 数论方法 有点非主流,很难想到。 代码随想录 视频讲解:动态规划中如何初始化很重要!| LeetCode:62.不同路径_哔哩哔哩_bilibili class Solution {public int uniquePaths(int m, int n) {int dp[][] = new int[m][n];//初…...
渗透测试之Web基础之Linux病毒编写——泷羽sec
声明: 学习视频来自B站UP主泷羽sec,如涉及侵权马上删除文章。本文只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频 (bilibili.com)https://space.bilibili.com/350329294 导读: 时刻…...
jmeter基础07_组件的层级
课程大纲 1. 优先级/执行顺序(一般情况) 同级组件:按组件先后顺序执行。如:同一层的线程组、同一层的http请求。 上下级组件:先执行外层(上级),再执行内层(下级ÿ…...
Nginx反向代理和负载均衡配置
一、疑问 在苍穹外卖里,浏览器发送的请求,比如登录,其url为http://localhost/api/employee/login, 而后端的路径是http://localhost:8080/admin/employee/login 两者不一致,数据是如何准确传输的呢? 二、…...
【379】基于springboot的防疫物资管理信息系统
摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装防疫物资管理信息系统软件来发挥其高效地信息处理的作用&am…...
Linux 各个目录作用
刚毕业的时候学习Linux基础知识,发现了一份特别好的文档快乐的 Linux 命令行,翻译者是happypeter,作者当年也在慕课录制了react等前端相关的视频,通俗易懂,十分推荐 关于Linux的目录,多数博客已有详细介绍…...
【Linux】文件操作的艺术——从基础到精通
🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长,行则将至 目录 📚前言:一切皆文件 📚一、C语言的文件接口 📖1.文件打…...
java中的运算符
大家好,今天来看看java中运算符的一些知识点,理解好运算符是我们在写代码的一大重点,那么我们就来看看吧。 运算符:对操作数进行操作时的符号.,不同运算筹操作的含义不同. 一、算术算片. 1、基本四则运算符:加减乘除模(一*/%) 注意:都是二元…...
全面解析 C++ STL 中的 set 和 map
C 标准模板库(STL)中的关联式容器以其强大的功能和高效性成为开发者解决复杂数据组织问题的重要工具。其中,set 和 map 是最常用的两类关联容器。本篇博客将从基本特性、底层实现、用法详解、高级案例以及性能优化等多个角度,详细…...
css:怎么设置div背景图的透明度为0.6不影响内部元素
目录 1.前言 2.解决思路 3.具体实例 4.另外一种实例 5.总结 1.前言 div背景图为project-bg.png,设置div透明度为0.6;div内的名称、数值受透明度影响颜色显示不正常;怎么设置背景图的透明度为0.6不影响内部元素; 2.解决思路 …...
Kubernetes ConfigMaps
文章目录 简介创建ConfigMaps通过命令行使用字面值创建 ConfigMap。从文件创建ConfigMaps从多个文件创建 ConfigMap从目录创建 ConfigMap使用 YAML 创建 ConfigMap 使用ConfigMaps使用 ConfigMaps作为环境变量使用 ConfigMap 作为卷挂载使用 ConfigMap 中的特定的key ConfigMap…...
前端热门面试题目[一](HTML、CSS、Javascript、Node、Vue、React)
如何设计一个前端页面,实现PC端访问展示Web应用,移动端访问展示H5应用? 为了实现这一功能,通常需要使用响应式设计或者服务器端检测用户设备并返回相应的页面。以下是一些实现方法: 响应式设计:通过CSS媒…...
Swift 宏(Macro)入门趣谈(五)
概述 苹果在去年 WWDC 23 中就为 Swift 语言新增了“其利断金”的重要小伙伴 Swift 宏(Swift Macro)。为此,苹果特地用 2 段视频(入门和进阶)颇为隆重的介绍了它。 那么到底 Swift 宏是什么?有什么用&…...
ES6 Set、Map、WeakSet、WeakMap 四者辨析与实战应用详解
在 ES6 中,Set 和 Map 是两种非常重要的新增数据结构,它们都具有独特的特性和用途,能够帮助开发者更高效地处理和管理数据。除此之外,WeakSet 和 WeakMap 作为这两种数据结构的变种,也具有一些特殊的功能。下面我会从 Set 数据结构、Map 数据结构、WeakSet 和 WeakMap 对比…...
【数据结构】哈希表实现
前言 在本篇博客中,作者将会带领你使用C语言来实现一个哈希表。 一.什么是哈希表 在实现哈希表之前,我们先来学习一下什么是哈希表。 在传统的数据结构中,例如数组,链表和二叉平衡树等数据结构,这些数据结构的元素关键…...
Verilog的线与类型与实例化模块
1、线与类型 在Verilog中,线与(wire-AND)类型通常用于描述多个信号进行逻辑与(AND)操作的电路行为。虽然Verilog本身没有直接定义一种名为“线与”的数据类型,但可以通过使用wire类型结合特定的逻辑操作来…...
芯片测试-RF中的S参数,return loss, VSWR,反射系数,插入损耗,隔离度等
RF中的S参数,return loss, VSWR,反射系数,插入损耗,隔离度 💢S参数💢💢S11与return loss,VSWR,反射系数💢💢S21,插入损耗和增益&#…...
强化学习的几个主要方法(策略梯度、PPO、REINFORCE实现等)(上)
本笔记有大量参考蘑菇书EasyRL https://datawhalechina.github.io/easy-rl/#/ 包括其配图和部分文本。 1. 基本概念 1.1 基本流程 强化学习是一种学习框架,其中智能体(Agent) 通过与 环境(Environment) 的交互&#…...
Git远程仓库操作
文章目录 远程仓库连接Gitee克隆代码 多人协同问题说明 🏡作者主页:点击! 🤖Git专栏:点击! ⏰️创作时间:2024年12月1日13点10分 远程仓库 Git 是分布式版本控制系统,同一个 Git …...
GAGAvatar: Generalizable and Animatable Gaussian Head Avatar 学习笔记
1 Overall GAGAvatar(Generalizable and Animatable Gaussian Avatar),一种面向单张图片驱动的可动画化头部头像重建的方法,解决了现有方法在渲染效率和泛化能力上的局限。 旋转参数 现有方法的局限性: 基于NeRF的方…...
什么是VISUAL STUDIO CODE (V S CODE)
Visual Studio Code(简称VS Code)是由微软开发的一个免费的、开源的源代码编辑器。它是一个轻量级但功能强大的工具,支持多种编程语言和框架,广泛用于开发各种应用程序,尤其是Web开发。VS Code具备以下特点:…...
2024年09月中国电子学会青少年软件编程(Python)等级考试试卷(三级)答案 + 解析
青少年软件编程(Python)等级考试试卷(三级) 分数:100 题数:38 一、单选题(共25题,共50分) 1. 以下表达式的值为True的是?( ) A. all( ,1,2,3) B. any([]) C. bool(abc) D. divmod(6,0)...
C++初阶——动态内存管理
目录 1、C/C内存区域划分 2、C动态内存管理:malloc/calloc/realloc/free 3、C动态内存管理:new/delete 3.1 new/delete内置类型 3.2 new/delete自定义类型 4、operator new与operator delete函数 5、new和delete的实现原理 5.1 内置类型 5.2 自定…...
如何查看阿里云ddos供给量
要查看阿里云上的 DDoS 攻击量,你可以通过阿里云的 云盾 DDoS 防护 服务来进行监控和查看攻击数据。阿里云提供了详细的流量监控、攻击日志以及攻击趋势分析工具,帮助用户实时了解 DDoS 攻击的情况。以下是九河云总结的查看 DDoS 攻击量的步骤࿱…...
MySQL中的事务隔离全详解
第一部分:MySQL事务的特性与并行事务引发的问题 1. 什么是事务及其四大特性(ACID)? 事务(Transaction)是数据库操作的基本单位,它将一组操作组合在一起,以确保这些操作作为一个整体…...
异常--C++
文章目录 一、异常的概念及使用1、异常的概念2、异常的抛出和捕获3、栈展开4、查找匹配的处理代码5、异常重新抛出6、异常安全问题7、异常规范 二、标准库的异常 一、异常的概念及使用 1、异常的概念 异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并…...
SeggisV1.0 遥感影像分割软件【源代码】讲解
在此基础上进行二次开发,开发自己的软件,例如:【1】无人机及个人私有影像识别【2】离线使用【3】变化监测模型集成【4】个人私有分割模型集成等等,不管是您用来个人学习还是公司研发需求,都相当合适,包您满…...
锁-读写锁-Swift
实现一 pthread_mutex_t: ReadWriteLock/Sources/ReadWriteLock at main SomeRandomiOSDev/ReadWriteLock GitHub https://swiftpackageindex.com/reers/reerkit/1.0.39/documentation/reerkit/readwritelock/ // // Copyright © 2022 reers. // // Pe…...
wordpress的主题文件夹/长尾关键词挖掘工具
2019独角兽企业重金招聘Python工程师标准>>> 这是一场不同寻常的雪,因为很久已经没有白色的雪落在这片大地上了。 我们在飞驰的火车上,去我们付出后半生努力汗水的地方。 雪苍茫一片,城市也是银白的。 转载于:https://my.oschina.…...
wordpress在线演示/网络推广都需要做什么
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其…...
深圳网站建设联雅网络/正规seo需要多少钱
【项目背景】 近年来,信息技术的飞速发展使人们获取、交流和处理信息的手段发生了巨大的变化,随着信息时代的到来,信息化发展也为公安工作带来了新的挑战和机遇。 随着全国电子政务进程的推进,国家提出了以“公安信息化工作”为核…...
社会题目可以在哪些网站上做/编写网页的软件
我告诉你开源php框架的symfony中的一个很有名的扩展sfGuard是怎么做的,可能可以给你提供一些思路:首先你的数据库需要一个rememberkey表:它包含了一下三个字段:user_id, remember_key(string(32),unique), ip_address,…...
网站添加缩略图/优化网站链接的方法
先说结论:使用命令行的rmdir总是可以把文件/文件夹清除,但是MFC自己的 DeleteFile函数有时出现删除失灵的情况(qt的QDir::removeRecursively()也有类似问题)。1) 使用cmd命令删除文件夹 出处:https://www..com/jiangyi666/p/6638815.htmlrmdi…...
wordpress无法连接app/seopeixun com cn
2019独角兽企业重金招聘Python工程师标准>>> 上一篇讲完了java内存模型中线程私有部分(程序计数器、虚拟机栈、本地方法栈),这篇讲下所有线程公有部分 问:元空间(MetaSpace)和永久代(PermGen)的区别? 元空间使用本地内…...