JVM 第二部分-2(堆,方法区)

4.堆

  • 一个Java程序(main方法)对应一个jvm实例,一个jvm实例只有一个堆空间
  • 堆是jvm启动的时候就被创建,大小也确定了。大小可以用参数设置。堆是jvm管理的一块最大的内存空间 核心区域,是垃圾回收的重点区域
  • 堆可以位于物理上不连续的内存空间中,但在逻辑上是连续的
  • 所有的线程共享堆,堆里还有TLAB(线程私有的缓冲区 Thread Local Allocation Buffer)
  • 所有的对象及数组分配在堆里(如果对象在方法里面没有逃逸,理论上可以栈上分配,取决于jvm设计者的选择)
  • 在方法结束后,堆中的对象不会被马上移除,垃圾回收时才会移除
  • 内存细分:现代垃圾收集器大部分都基于分代收集理论设计
    • 新生区=新生代=年轻代 养老区=老年区=老年代 永久区=永久代
    • Java7及之前,堆内存逻辑上分为三部分:
      • 新生代 Young/New Generation Space 又被分为 Eden区和 Survivor 0区 Survivor 1区(不空的为from区 空的为to区,to区是下一次要放的区域)
      • 老年代 Old/Tenure Generation Space
      • 永久代 Permanent Space
    • Java8及之后,堆内存逻辑上分为三部分:新生代 老年代 元空间(Meta Space)
    • 事实上,永久代 / 元空间 具体是方法区实现
    • 当面试题问 jdk8内存结构有什么改变,要提出 永久代变成元空间
  • 设置堆空间大小
    • -Xms 用于设置堆空间(年轻代+老年代,不含元空间)初始大小(等价于 -XX:InitialHeapSize) 例子:-Xms10m
    • -Xmx 用于设置堆空间最大大小(等价于 -XX:MaxHeapSize)例子:-Xmx10m
    • 一旦堆空间超过 -Xmx 的值,就会报OOM
    • 通常会设置 -Xms -Xmx为一样的值,目的是为了能够在Java垃圾回收完之后,不用再重新分隔计算堆区的大小,从而提高性能
    • 默认情况下,初始内存 = 本机内存 / 64,最大内存 = 本机内存 / 4
  • 查看堆空间大小
    • java代码中 用Runtime.getRuntime().totalMemory() / 1024 / 1024 可以看到堆空间大小 多少兆
      • 【输出的值和设置的值不一样】因为survivor区只能用其中一个,所以所有加起来能用的区域就少一些
    • 或者cmd ,jps查看当前Java程序的进程id ,然后jstat -gc 进程id (代码加个 Thread.sleep() 执行长一些)
    • 或者在vm参数加 -XX:+PrintGCDetails
  • 年轻代和老年代
    • 堆中可以分成两类对象
      • 一种是生命周期较短的对象,创建和消亡十分迅速
      • 另一种是生命周期比较长的对象,有些甚至和jvm生命周期一样
    • 配置年轻代和老年代的比例(一般用默认值)
      • 默认:-XX:NewRatio=2,表示 年轻代/老年代 = 1/2,年轻代占堆 1/3
    • 配置 Eden区和Survivor区比例(一般用默认值)
      • 默认:-XX:SurvivorRatio=8 ,表示 Eden区:Survivor 0:Survivor 1=8:1:1
        • 不过直接看不是这个比例,因为jvm有自适应的内存分配策略,可能可以用 -XX:-UseAdaptiveSizePolicy(不太管用)
        • 可以显式设置 -XX:SurvivorRatio=8
    • 配置 Eden区最大大小(一般不用)【同时设置了比例和这个,以这个为准】
      • -Xmn60m
    • 几乎所有的对象都是从Eden区new出来的(很大的除外,很大的对象在Eden区YGC之后还放不下就放Old区)
  • 对象分配过程
    • 1.new的对象先分配到Eden区
    • 2.如果Eden区满了,会触发young/minor gc,垃圾回收Eden区和Survivor区。Eden区 和 Survivor区中没被回收的对象放到空的Survivor区,对象的age+1。然后再把新对象放到Eden区
    • 3.如果这个对象过大,在Eden区YGC之后还放不下就放Old区
    • 4.young gc后,当对象的age=15时,就是15次垃圾回收都没有被回收,就会放到 Old区
      • 这个次数可以设置。-XX:MaxTenuringThreshould=15
    • 5.young gc后,当Survivor区满了,会把Survivor区的对象放到Old区,即使不够15次
    • 6.young gc后,当Old区满了,就会 Full gc
    • (Survivor区满了,不会触发GC)
    • 7.若Old区发生了Full gc 后,还是满的,就会OOM
    • 【s0,s1区,复制之后有交换,谁空谁是to】
    • 【关于垃圾回收,频繁Eden区,很少Old区,几乎不在永久区/元空间】

请添加图片描述

  • GC
    • 针对hotspot jvm,按回收区域分为两大类型:一种的部分收集(Partial GC),一种是整堆GC(full gc)
    • 部分收集:在一部分堆空间进行垃圾回收
      • 新生代收集 (Minor GC / Young GC):只收集Eden区 Survivor区
      • 老年代收集(Major GC / Old GC):只收集 Old区
        • 目前,只有CMS GC会有单独收集老年代的行为
        • 很多时候,Major GC 和 Full GC混用,需要具体分辨是老年代回收还是整堆回收【很多帖子混淆】
      • 混合收集(Mixed GC)收集整个新生代及一部分老年代
        • 目前,只有G1 GC有这种行为
    • 整堆收集(Full GC):收集整个堆和方法区
    • 年轻代GC(Minor GC)触发机制:
      • 当Eden区空间不足时触发,Survivor区满不触发,清理的是Eden区和Survivor区
      • 因为Java对象大都是朝生夕灭的,所以Minor GC非常频繁,速度也比较快
      • Minor GC会引发STW,暂停其他用户线程,等垃圾回收结束,用户线程才恢复执行
    • 老年代GC(Major GC / Full GC 这样说不正确其实)触发机制:
      • 发生在Old 区
      • 出现Major GC 一般伴随着一次Minor GC (但非绝对,在Parallel Scavenge收集器的收集策略里就有直接进行Major GC 的策略选择过程)
        • 也就是在老年代空间不足时,会先尝试触发Minor GC。但之后空间如果还不足,则触发Major GC
      • Major GC 的速度比Minor GC慢10倍以上,STW的时间更长
      • 如果Major GC后,内存还不足,就OOM了
    • Full GC触发机制:(后面细讲)
      • 1.调用System.gc()时,系统建议使用Full GC,但是不必然执行
      • 2.老年代空间不足
      • 3.方法区空间不足
      • 4.通过Minor GC 后进入老年代的平均大小大于老年代的可用内存
      • 5.由Eden区,Survivor space0(From Space)区向Survivor space1(To Space)区进行复制时,对象大于To Space可用内存,则把对象转存到老年区,且老年区的可用内存小于该对象大小
      • Full GC 是开发或调优中要尽量避免的,这样暂停时间短一点
  • 为什么要把Java堆分代?不分代就不能工作嘛?
    • 其实不分代可以,分代是为了优化GC性能。不分代的话,就要扫描整个堆。扫描范围大,比较耗时。而进行分代,把新创建的对象放到一个区域,因为大部分的对象生命周期很短,那么就可以对这个区域进行频繁GC。不用扫描整个堆,提高效率、
  • 内存分配策略(或晋升(Promotion)规则)
    • 优先分配到Eden区
    • 大对象直接分配到老年代
      • 尽量避免程序中出现过多的大对象(不仅仅是因为占很多空间,容易导致频繁Major GC或Full GC。而且因为这些大对象大部分生命周期也很短,往往是Major GC或Full GC之后就被清楚掉,不值得放到老年代)
    • 长期存活的对象分配到老年代
    • 动态对象年龄判断
      • 如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄
    • 空间分配担保
      • -XX:HandlePromotionFailure 【Java7及以后,相当于默认开启此参数,改变设置也不起作用】
  • TLAB——堆全部都是共享的嘛?不是
    • 为什么有TLAB:因为堆是线程共享区域,而对象实例的创建在jvm中非常频繁,因此在并发环境下从对中划分空间是线程不安全的。为了避免多个线程操作同一地址,需要加锁的话,就会影响分配速度。有了TLAB,对象在TLAB里创建就不会有线程安全问题
    • 尽管不是所有的对象都能在TLAB内创建,但是TLAB确实是jvm内存分配的首选
    • 所有OpenJDK衍生出的jvm都有TLAB
    • -XX:UseTLAB 设置是否开启TLAB空间,默认开启
    • TLAB很小,默认占Eden区 1%
      • -XX:TLABWasteTargetPercent 设置TLAB占Eden百分比大小
    • 一旦对象在TLAB分配失败,就会在Eden中分配,使用时要加锁

请添加图片描述

  • 栈上分配—逃逸分析—堆是对象分配的唯一选择嘛?是(逃逸分析->栈上分配),也可以不是(取决于jvm设计者要不要在栈上分配)
    • 如果一个对象经过逃逸分析,发现没有逃逸,那么就会在栈上分配(不分配到堆上,减少GC压力)
    • 而淘宝的TaoBaoVM,其中的GCIH(GC invisible heap)技术实现off-heap,将生命周期较长的Java对象从heap中移至heap外,并且GC不能管理GCIH内的Java对象,从而降低GC回收频率,提升GC回收效率
    • **逃逸分析:**如果在方法内使用的对象,它会在除本方法外的其他地方用到,那就是逃逸
      • 比如:作为参数传入,通过return返回,给对象属性赋值,使用对象属性
      • 逃逸分析其实并不成熟。根本原因是无法保证做了逃逸分析的性能一定比不做好,因为逃逸分析也是一个相对耗时的过程。极端点就是经过逃逸分析发现没有一个对象是逃逸的,那么分析的过程就白白浪费了一些性能。
      • 虽然不成熟,但是也是即时编译器优化技术中一个十分重要的手段。
      • 重点:【通过逃逸分析,jvm会在栈上分配那些不会逃逸的对象,这种理论上是可行的,但是这取决于jvm设计者的选择。Oracle Hotspot JVM中并没有这样做,这一点在逃逸分析相关的文档里已经说明,所以,可以明确所以的对象实例都是创建在堆上。在实际代码测试中,运行速度加快,是因为虽然没有在栈上分配,但是jvm做了标量替换,加快了速度】
    • 参数设置:
      • 在Java7及以后,Hotspot默认开启逃逸分析
      • 如果使用的是较早的版本
        • -XX:+DoEscapeAnalysis 显式开启逃逸分析
        • -XX:+PrintEscapeAnalysis 查看逃逸分析的筛选结果
    • 所以,能使用局部变量,就不要在方法外定义
    • 使用逃逸分析,jvm能做的优化
      • 1.栈上分配
      • 2.同步省略 / 锁消除:在动态编译同步块时,就是运行时,JIT编译器通过逃逸分析判断个对象是否只能从一个线程被访问到。如果是,那么JIT编译器在编译这个同步块时会取消对这部分代码的同步。大大提高性能和并发(不过字节码文件还是显示有锁的)
      • 3.分离对象或标量替换:【简单的说就是不用对象,而是创建几个和对象属性对应的变量】有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在堆,而是存储在栈中
        • 标量就是一个无法再分解成更小数据的数据。聚合量就可以再分解。对象就是聚合量
        • JIT阶段,如果经过逃逸分析,发现对象不会逃逸,就会把那个对象分解成若干个标量。这个过程就是标量替换【比如下面两张图】
        • 标量替换可以减少对象的创建,减少堆内存的分配,大大减少堆内存的占用。为栈上分配提供了很好的基础
        • 参数:-XX:+EliminateAllocations 开启了标量替换,默认开启,允许将对象打散分配在栈上

请添加图片描述

请添加图片描述

  • 常用命令
    • -XX:+PrintFlagsInitial:查看所有的参数的默认初始值
    • -XX:+PrintFlagsFinal:查看所有的参数的最终值(可能会存在修改,不再是初始值)
    • -Xms:初始堆空间内存(默认为物理内存的1/64)【常用】
    • -Xmx:最大堆空间内存(默认为物理内存的1/4)【常用】
    • -Xmn:设置新生代的大小。(初始值及最大值)
    • -XX:NewRatio:配置新生代与老年代在堆结构的占比
    • -XX:SurvivorRatio:设置新生代中Eden和s0/S1空间的比例
    • -Xx:MaxTenuringThreshold:设置新生代垃圾的最大年龄 【常用】
    • -XX:+PrintGCDetails:输出详细的GC处理日志 【常用】
    • 打印gc简要信息:1.-XX:+PrintGC 2.-verbose:go
    • -XX:UseTLAB 设置是否开启TLAB空间,默认开启
    • -XX:TLABWasteTargetPercent 设置TLAB占Eden百分比大小
    • -XX:+DoEscapeAnalysis 显式开启逃逸分析,默认开启
    • -XX:+PrintEscapeAnalysis 查看逃逸分析的筛选结果 【常用】
    • -XX:+EliminateAllocations 开启了标量替换,默认开启,允许将对象打散分配在栈上
    • -XX:HandlePromotionFailure:是否设置空间分配担保 【Java7及以后,相当于默认开启此参数,改变设置也不起作用】

请添加图片描述

5.方法区 / 元空间

请添加图片描述

请添加图片描述

(对象类型数据 就是 类的数据)

方法区 / 元空间

  • 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。
  • 方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。
  • 在Jdk7及以前,习惯把方法区称为永久代。Jdk8及以后,永久代变成了元空间
  • 本质上,方法区和永久代不等价。仅是对Hotspot而言是等价的。《Java虚拟机规范》对如何实现方法区,不做统一要求。例如:BEA 的 JRockit / IBM 的 J9不存在永久代的概念
    • 现在看来,当年用永久代,不是一个好想法。因为它导致Java程序更容易OOM(超过 -XX:MaxPermSize上限)
  • 元空间与永久代类似,都是对jvm规范中方法区的实现。他们最大的区别在于:元空间不是使用Java虚拟机的内存,而是使用本地内存
    • 元空间不仅仅是名称变了,内部结构也变了
  • 方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。
    • jdk7及以前
      • -XX:PermSize=60m 来设置永久代初始分配空间。默认值是20.75m
      • -XX:MaxPermSize=60m 来设置永久代最大可分配空间。32位机器默认64m,64位机器默认82m
      • 当jvm加载的类超过最大大小,会报 java.lang.OutofMemoryError:PermGen space
    • jdk8及以后
      • 元数据区大小可以使用参数-XX:MetaspaceSize=100m和-XX:MaxMetaspaceSize指定
      • 默认值依赖于平台。window下,-XX:MetaspaceSize是21m,-XX:MaxMetaspaceSize是-1,即没有限制,会一直用系统内存
  • 高水位线(在jdk8及以后)
    • 初始的高水位线 和 -XX:MetaspaceSize的值一样。一旦元空间大小触及到这条线,Full GC就会被触发并卸载没用的类(即这些类对应的类加载器不再存活),然后这个高水位线就会被重置。新的高水位线的值取决于GC后释放了多少元空间。如果释放的空间不足,那么在不超过MaxMetaspaceSize时,适当提高改值。如果释放的空间过多,适当降低该值。
    • 如果初始的 高水位线设置过低,上述 高水位线调整情况会发生很多次,也会频繁Full GC。建议将-XX:MetaspaceSize设置为一个相对较高的值
  • 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误:java.lang.OutofMemoryError:PermGen space (java7及之前) 或者 java.lang.OutofMemoryError:Metaspace(java8及以后)
    • 加载大量的第三方的jar包会OOM:Tomcat部署的工程过多(30-50个) , 大量动态的生成反射类
  • 关闭JVM就会释放这个区域的内存。
  • OOM的例子:

请添加图片描述

请添加图片描述

  • 方法区存的内容
    • 存放已被虚拟机加载的类型信息,常量,静态变量,JIT即时编译器编译后的代码缓存等。(随jdk版本不同,会有些变化)
    • 类型信息(类,接口,枚举,注解)
      • 这个类型的完整有效名称(全名=包名.类名)
      • 这个类型直接父类的完整有效名(对于接口和Object类都没有父类)
      • 这个类型的修饰符(public,abstract,final的某个子集)
      • 这个类型实现的接口的一个有序列表
    • 域(Field)信息(就是类的属性信息)
      • jvm必须在方法区中保存类型的所有域的相关信息以及域的声明顺序
      • 域的相关信息包括:域名称、域类型、域修饰符(public,private,protected,static,final,volatile,transient的某个子集)
    • 方法(Method)信息
      • jvm必须在方法区中保存所有方法的以下信息以及域的声明顺序
      • 方法名称
      • 方法的返回类型(或 void)
      • 方法参数的数量和类型(按顺序)
      • 方法的修饰符(public,private,protected,static,final,synchronized,native,abstract的一个子集)
      • 方法的字节码(bytecodes)、操作数栈、局部变量表及大小(abstracth和native方法除外)
      • 异常表(abstracth和native方法除外)
        • 每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引
    • 类变量(static)
      • 没加final的:静态变量和类关联在一起,随着类的加载而加载,它们成为类数据在逻辑上的一部分,但是放到堆中
      • 加了final的:在编译期就确定下来了,放到元空间
    • 运行时常量
      • 方法区中的运行时常量池和字节码文件中的常量池的对应起来的
        • Java中的字节码需要数据支持,通常这种数据很大不能直接放到字节码文件中,换另一种方式,可以存到常量池,在动态链接时再引用进来
        • 字节码的常量池包括各种字面量,和对类型、域、方法的符号引用
      • jvm为每个已加载的类型(类或接口)都维护一个常量池,通过索引访问
      • 运行时常量池 把 字节码文件的常量池中的符号引用 转成了直接引用
      • 运行时常量池 相当于Class文件常量池的另一重要特征是:具备动态性(有些没有的东西会自动加进去)
      • 运行时常量池类似于传统编程语言中的符号表(symbol table),但是它所包含的数据却比符号表要更加丰富一些
      • 如果创建运行时常量池超过方法区的最大值,会OOM
    • 还包含了加载这个字节码文件的 类加载器

请添加图片描述

  • 方法区的演进细节
    • jdk1.6及之前,有永久代,静态变量存放在永久代上

    • jdk1.7,有永久代,但已经逐步“去永久代”,字符串常量池、静态变量保存到堆中

    • jdk1.8及以后,无永久代,类型信息、字段、方法、常量保存在本地内存的元空间。但字符串常量池,静态变量仍然在堆中

    • 【要注意:如果静态变量是对象的引用。比如:public static a = new int[10] 无论是哪个jdk,数组都是在堆中。因为它是被new 出来的对象。而变量a在不同jdk的位置就不一样】

      ![请添加图片描述](https://img-blog.csdnimg.cn/direct/9102dc07d68e44f7be667f656dc955c5.png)
      

请添加图片描述

请添加图片描述

请添加图片描述

  • 为什么元空间要替代永久代?
    • 1.为永久代设置大小是很难的。设置小了在某些场景下容易OOM,特别是要动态加载很多类的时候。设置大了浪费空间。元空间使用本地内存,不用设置,仅仅受内存大小的限制
    • 2.对永久代进行调优是很困难的。Full GC的时候会对方法区的垃圾回收。判断类型信息是否要清理比较满分。所以Full GC比较麻烦,调优也比较困难。用本地内存,空间大一些,Full GC也会少一些
  • 为什么StringTable要放到堆里
    • jdk7中将StringTable放入堆中。因为永久代很少进行垃圾回收,只有触发Full GC的时候才会进行清理。Full GC只有在老年代空间不足,或者永久代空间不足才会触发,这就导致StringTable的回收效率不高。在运行过程中,大量的字符串常量被创建,很多都是不用的,放到堆中可以及时清理
  • 方法区的垃圾回收
    • 有的虚拟机支持方法区GC,有的没有GC。Java的虚拟机规范对方法区的约束很宽松,方法区实不实现垃圾回收都可以。(JDK 11的ZGC收集器就不支持类卸载)
    • 方法区的回收效果比较难以让人满意,尤其是类型的卸载,条件很苛刻。但是这部分区域的回收有时又确实是必要的。以前Sun公司的Bug列表中,曾出现的几个严重的BUG就是因为低版本的hotspot对方法区未完全回收导致内存泄露
    • 主要回收两部分内容:常量池中废弃的常量 以及 不再使用的类型
      • 常量包括字面量 和 符号引用
        • 符号引用包括,类和接口的全限定名,字段的名称和描述符,方法的名称和描述符
      • 常量只要没有地方使用 就可以回收
      • 但是类型是否回收的判断条件很苛刻,下面是被回收的前提(但是满足了也不一定会回收)
        • 1.该类没有实例。也没有任何派送子类的实例
        • 2.加载该类的类加载器已经被回收。除非是精心设计的可替换类加载器的场景,比如OSGI,JSP的重加载等,否则很难达成
        • 3.该类对应的java.lang.class对象没有被任何地方引用,无法在任何地方通过反射访问该类的方法
      • Java虚拟机被允许对满足上述三个条件的无用类进行回收,这里说的仅仅是“被允许”,而并不是和对象一样,没有引用了就必然会回收。关于是否要对类型进行回收,HotSpot虚拟机提供了-Xnoclassgc参数进行控制,还可以使用-verbose:class以及-XX:+Traceclass-Loading、-XX:+TraceClassUnLoading查看类加载和卸载信息
    • 在大量使用反射、动态代理、CGLib等字节码框架,动态生成JSP,以及OSGi这类频繁自定义类加载器的场景中,通常需要Java虚拟机具备类型卸载的能力,以保证不会对方法区造成过大的内存压力。

请添加图片描述请添加图片描述

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

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

相关文章

洛谷P1509找啊找啊找GF

题解:这题我们需要考虑两个因素 ,既要有钱,也需要有人品,但是呢,还想花最少得时间泡到最多的女生,那么这题我们就要用到以往的二维dp数组,但是真的是二维的吗?不,因为要考…

如何让大项目自动化测试更加灵活简洁

如何把大象放到冰箱里?第一打开冰箱门,第二把大象放进去,第三把冰箱门关好。 这个问题言外之意是大象那么大,怎么能放进冰箱,为什么要把大象放冰箱,就开始纠结这个问题了,它是想表明不用太多纠结…

Day20-磁盘管理

Day20-磁盘管理 1. cut 切:2. 磁盘历史和内外部物理结构介绍2.1 磁盘发展趋势和实现措施2.2 磁盘知识的体系结构2.3 机械磁盘的外部结构2.4 SSD固态硬盘的外部结构2.5 固态硬盘内部结构2.6 缓存在服务器各硬件上的速度和大小对比另类维度图解,从上到下由高速到低速&…

DataX及Datax-web杂记

👽个人博客:https://everspring.github.io/ 👽公众号:爱历史的IT男 一. DataX调试 DataX之前调试不是很方便,要打包后才能调试。23年7月后一位叫"FuYouJ "的开源者提交了datax-example模块,就方…

EasyRecovery2024国产免费的手机数据恢复软件

一、功能介绍 EasyRecovery手机数据恢复软件是一款功能全面的数据恢复工具,专为移动设备设计。其主要功能包括: 文件恢复:能够恢复手机中因各种原因丢失的文件,如照片、视频、音频、文档等。深度扫描:通过深度扫描手…

【数据结构】实现栈

大家好,我是苏貝,本篇博客带大家了解栈,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 一 .栈的概念及结构二 .栈的实现栈的结构体初始化销毁栈顶插入栈顶删除显示栈顶元素是否为空栈的大…

USB - Linux Kernel Menuconfig

Linux kernel,make menuconfig,和USB相关的,在主菜单选择Device Drivers。 Device Drivers下面,找到USB support。 在USB support下面,就可以对USB相关的item进行设置。 按照从上到下的顺序,打开的设置依次…

【C++入门】缺省参数 | 函数重载

目录 4.缺省参数 4.1缺省参数的概念 4.2缺省参数分类 4.3声明和定义分离(声明使用缺省参数) 4.🐍声明和定义分离到链接 5.函数重载 5.1函数重载的概念 5.2可执行程序的形成步骤 5.3C支持函数重载的原理—名字修饰(name Mangling) 4.…

Linux学习之信号

目录 1.信号的概念 2.信号的产生 3.信号的保存 4.信号的捕捉 信号的其它内容: SIGCHLD信号 1.信号的概念 在Linux中,信号是一种用于进程之间通信的基本机制。它是一种异步事件通知,用于通知进程发生了某些事件。如下是一些常见的Linux信…

[计算机网络]--五种IO模型和select

前言 作者:小蜗牛向前冲 名言:我可以接受失败,但我不能接受放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、五种IO…

线性规划问题的高斯消元法

线性规划的算法和解方程组的方法很像,常用的方程组的解法叫做高斯消元法,对于高斯消元法的基本流程,现给定一组线性方程: 添加图片注释,不超过 140 字(可选) 对于给定的线性方程组,目的是将方程组中同时能够满足三个等式的变量x,y,z求解出来,对于高斯消元法的基本过程…

【精通Spring】基于注解管理Bean

个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…

集智书童 | YOLO+混合注意力机制 | YOLOv5再加4.3%才可以做对手,Transformer混合设计依旧可以卷

本文来源公众号“集智书童”,侵权删,干货满满。YOLOv5重出江湖! 原文链接:https://mp.weixin.qq.com/s/vb7HsA0fKDgRc3uC8Z-2yw 在工业生产过程中,由于低效率、不统一的评估、高成本以及缺乏实时数据,传统…

C语言-指针(上)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 本篇文章将为大家介绍C语言中的核心内容-指针,指针在C语言的中知识内容比…

Java 小项目开发日记 04(文章接口的开发、oss图片上传)

Java 小项目开发日记 04&#xff08;文章接口的开发、oss图片上传&#xff09; 项目目录 配置文件&#xff08;pom.xml&#xff09; <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:sc…

机器学习:集成学习(Python)

一、Adaboost算法 1.1 Adaboost分类算法 adaboost_discrete_c.py import numpy as np import copy from ch4.decision_tree_C import DecisionTreeClassifierclass AdaBoostClassifier:"""adaboost分类算法&#xff1a;既可以做二分类、也可以做多分类&#…

uniapp的h5端在线预览文件

步骤如下&#xff1a; 1、下载需要准备的工具文件包 2、将其解压到/static/pdf文件夹下,如图&#xff1a; 3、创建在线查看文件的页面&#xff1a; <template><view><web-view :src"path"></web-view></view> </template>&l…

JavaScript练手小技巧:一文看懂<script>标签的 ansyc 和 defer

<script>标签的 ansyc 和 defer 属性。只对外部加载 JS 文件有效。 <script src"js/app.js" async></script> <script src"js/app.js" defer></script> 普通加载 js&#xff08;同步加载&#xff09;&#xff1a;会打断 …

Vue3 isProxy,isReactive,isReadonly 三者解析

1、isProxy 作用&#xff1a;判断当前数据是否为代理数据。 注意&#xff1a;它只对通过 reactive&#xff0c;readonly&#xff0c;shallowReactive&#xff0c;shallowReadonly 这四个方法包裹的数据返回true&#xff0c;对于 ref 以及通过 new Proxy 代理的数据返回都是fal…

ChatGPT科研与AI绘图及论文高效写作教程

原文链接&#xff1a;ChatGPT科研与AI绘图及论文高效写作教程 2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电…