【Java八股文总结】之JVM

news2025/1/12 6:06:12

文章目录

    • JVM
      • 一、JVM内存区域
        • 1、运行时数据区域
          • 1、程序计数器
          • 2、java虚拟机栈
            • Q:栈可能出现的两种错误
          • 3、本地方法栈
          • 4、堆
            • Q:堆中会出现的错误
            • Q:堆中对象的分配过程
          • 5、方法区
          • Q:堆和栈的区别?
        • 2、为什么要将永久代(PermGen)替换为元空间(MetaSpace)呢?
          • 1、方法区的常用参数有?
          • 2、运行时常量池
          • 3、字符串常量池
          • 4、jdk1.7 为什么将字符串常量池移到堆中?
          • 5、直接内存
        • 3、对象创建过程
          • Q:JVM创建对象,如何保证线程安全性?
          • 4、Java内存分配方式
          • 5、Java对象内存布局
            • Q:对象怎么访问定位?
        • 6、JVM中对象及常量、局部变量、全局变量的存储位置
        • 7、Java虚拟机的生命周期
      • 二、JVM 垃圾回收
        • 1、对象死亡的判断方法
        • 2、哪些对象可以作为GC Roots 呢?
        • 3、常见的引用类型(强软弱虚)
          • Q:如何判断一个常量是废弃变量?如何判断一个类是无用的类?
        • 4、垃圾回收算法
        • 5、垃圾回收器
          • CMS收集器
          • G1
          • Q:有了CMS,为什么还要引入G1?
          • Q:垃圾回收器负责的3个任务
        • 6、Minor GC/Young GC、Major GC/Old GC、Mixed GC、Full GC 都是什么意思?
          • Q:Minor GC的触发条件?
          • Q:什么时候会触发Full GC ?
          • Q:对象什么时候进入老年代?
      • 三、类加载过程
        • 1、类的生命周期
        • 2、类加载过程
          • 1、加载
          • 2、验证
          • 3、准备
          • 4、解析
          • 5、初始化
            • Q:初始化开始的时机
          • 6、卸载
        • 3、Java中的类加载器
          • Q:为什么要自定义类加载器?
          • Q:如何实现自定义类加载器?
        • 4、双亲委派模型
          • Q:双亲委派模型实现步骤?
          • Q:双亲委派模型的好处?
          • Q:如何判断两个Class对象是否是一个类?
          • Q:不想使用双亲委派模型怎么解决?
          • Q:3次打破双亲委派机制的案例?
          • Q:如何实现热部署?
        • 5、Tomcat的类加载机制?
      • 四、JVM调优参数
      • 五、JVM调优
        • 1、常用的命令行性能监控和故障处理工具?
        • 2、JVM可视化的性能监控和故障处理工具有?
        • 3、线上服务CPU占用过高怎么排查?
        • 4、内存飙升怎么排查?
        • 5、频繁的年轻代垃圾回收怎么办?
        • 6、频繁的整堆垃圾回收(full GC)怎么办?
        • 7、内存泄漏和内存溢出如何排查?

JVM

一、JVM内存区域

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、运行时数据区域

在这里插入图片描述
在这里插入图片描述
线程私有: 程序计数器、虚拟机栈、本地方法栈
线程共享: 堆、方法区、直接内存(非运行时数据区的一部分)
JDK 1.8同JDK 1.7比,最大的差别就是:元数据区取代了永久代。元空间与永久代之间最大的区别在于:元数据空间并不在虚拟机中,而是使用本地内存。

1、程序计数器

在这里插入图片描述

2、java虚拟机栈

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Q:栈可能出现的两种错误

在这里插入图片描述

3、本地方法栈

在这里插入图片描述

4、堆

在这里插入图片描述
在这里插入图片描述

Q:堆中会出现的错误

在这里插入图片描述

Q:堆中对象的分配过程
  1. new 的对象先放在 Eden 区,大小有限制。
  2. 如果创建新对象时,Eden 空间填满了,就会触发 Minor GC,将 Eden 不再被其他对象引用的对象进行销毁,再加载新的对象放到 Eden 区,特别注意的是 Survivor 区满了是不会触发 Minor GC 的,而是 Eden 空间填满了,Minor GC 才顺便清理 Survivor 区。
  3. 将 Eden 中剩余的对象移到 Survivor0 区。
  4. 再次触发垃圾回收,此时上次 Survivor 下来的,放在 Survivor0 区的,如果没有回收,就会放到 Survivor1 区。
  5. 再次经历垃圾回收,又会将幸存者重新放回 Survivor0 区,依次类推。
  6. 默认是 15 次的循环,超过 15 次,则会将幸存者区幸存下来的转去老年区,jvm 参数设置次数 : -XX:MaxTenuringThreshold=N 进行设置。
  7. 频繁在新生区收集,很少在养老区收集,几乎不在永久区/元空间搜集。
5、方法区

在这里插入图片描述
在这里插入图片描述

Q:堆和栈的区别?

在这里插入图片描述

2、为什么要将永久代(PermGen)替换为元空间(MetaSpace)呢?

在这里插入图片描述

1、方法区的常用参数有?

在这里插入图片描述

2、运行时常量池

在这里插入图片描述

3、字符串常量池

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、jdk1.7 为什么将字符串常量池移到堆中?

在这里插入图片描述

5、直接内存

在这里插入图片描述

3、对象创建过程

①类加载(判断类是否被加载、解析、初始化过) --> ②分配内存(分配内存的方式) --> ③初始化零值 --> ④设置对象头 --> ⑤执行init方法
在这里插入图片描述
在这里插入图片描述

Q:JVM创建对象,如何保证线程安全性?
  • 采用 CAS分配重试 的方式来保证更新操作的原子性。
  • 每个线程 在Java堆中预先分配一小块内存 ,也就是本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),要分配内存的线程,先在本地缓冲区中分配,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定。
4、Java内存分配方式

在这里插入图片描述

5、Java对象内存布局

在这里插入图片描述
在这里插入图片描述

Q:对象怎么访问定位?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
HotSpot虚拟机主要使用 直接指针 来进行对象访问。

6、JVM中对象及常量、局部变量、全局变量的存储位置

  • 局部变量
    基本数据类型:变量名和变量值存储在 方法栈 中。
    引用数据类型:变量值存储在 方法栈 中(存储的是堆中对象的内存地址),所指向的对象是存储在堆内存中(如new出来的对象)。

  • 全局变量
    基本数据类型:变量名和变量值存储在 内存中。
    引用数据类型:变量名存储的是所引用对象的内存地址,变量名和变量值存储在 内存中。

7、Java虚拟机的生命周期

Java虚拟机:执行Java程序。程序开始执行时它才运行,程序结束时它就停止。你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机。Java虚拟机总是开始于一个main()方法,这个方法必须是公有、返回void、只接受一个字符串数组。在程序执行时,你必须给Java虚拟机指明这个包或main()方法的类名。 Main()方法是程序的起点,它被执行的线程初始化为程序的初始线程。程序中其他的线程都由它来启动。Java中的线程分为两种:守护线程(daemon)和普通线程(non-daemon)。守护线程是Java虚拟机自己使用的线程,比如负责垃圾收集GC的线程就是一个守护线程。当然,你也可以把自己的程序用setDeamon设置为守护线程。包含Main()方法的初始线程不是守护线程。只要Java虚拟机中还有普通的线程在执行,Java虚拟机就不会停止。如果有足够的权限,你可以调用exit()方法终止程序。

二、JVM 垃圾回收

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、对象死亡的判断方法

在这里插入图片描述
在这里插入图片描述

2、哪些对象可以作为GC Roots 呢?

在这里插入图片描述

3、常见的引用类型(强软弱虚)

在这里插入图片描述
在这里插入图片描述

Q:如何判断一个常量是废弃变量?如何判断一个类是无用的类?

在这里插入图片描述

4、垃圾回收算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、垃圾回收器

在这里插入图片描述
注意:

  1. 注重吞吐量以及CPU资源情况下,优先选用Parallel Scavenge和Parallel Old收集器。
  2. CMS全称Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器。
  3. G1(garbage frist)优先回收垃圾存放最多的分区,垃圾回收暂停时间短,同时也能维持较好的吞吐量,还解决了CMS的浮动垃圾问题、内存碎片问题
  4. 吞吐量:CPU用于运行代码的时间与CPU总消耗时间的比值。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

CMS收集器

在这里插入图片描述
在这里插入图片描述

G1

在这里插入图片描述

Q:有了CMS,为什么还要引入G1?

优点: CMS最主要的优点在名字上已经体现出来——并发收集、低停顿
缺点: CMS同样有三个明显的缺点。

  1. 标记算法会导致内存碎片比较多。
  2. CMS的并发能力比较依赖于CPU资源,并发回收时垃圾收集线程可能会抢占用户线程的资源,导致用户程序性能下降。
  3. 并发清除阶段,用户线程依然在运行,会产生所谓的“浮动垃圾”(Floating Garbage),本次垃圾收集无法处理浮动垃圾,必须到下一次垃圾收集才能处理。如果浮动垃圾太多,会触发新的垃圾回收,导致性能降低。
    G1主要解决了内存碎片过多的问题。
Q:垃圾回收器负责的3个任务

①分配内存;②确保被引用对象的内存不被错误的回收;③回收不在被引用的对象的内存空间。

6、Minor GC/Young GC、Major GC/Old GC、Mixed GC、Full GC 都是什么意思?

  • 部分收集 (Partial GC): 指目标不是完整收集整个Java堆的垃圾收集,其中又分为:

1、新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。当Eden区没有足够的空间时,就会触发Young GC来清理新生代。
2、老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。
3、混合收集(Mixed GC):指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。

  • 整堆收集(Full GC): 收集整个Java堆和方法区的垃圾收集。
Q:Minor GC的触发条件?

① eden区满的时候,会触发Minor GC。
② 新创建的对象大小大于Eden区所剩下的空间大小时,会触发Minor GC。

Q:什么时候会触发Full GC ?

在这里插入图片描述

Q:对象什么时候进入老年代?

在这里插入图片描述

  • 长期存活的对象将进入老年代
    在对象的对象头信息中存储着对象的迭代年龄,迭代年龄会在每次YoungGC之后对象的移区操作中增加,每一次移区年龄加一。当这个年龄达到15(默认)后,这个对象将会被移入老年代。
    可以通过这个参数设置这个年龄值。-XX:MaxTenuringThreshold
  • 大对象直接进入老年代
    有一些占用大量连续内存空间的对象在被加载就会直接进入老年代。这样的大对象一般是一些数组,长字符串之类的。
    HotSpot虚拟机提供了这个参数来设置。-XX:PretenureSizeThreshold
  • 动态对象年龄判定
    为了能更好地适应不同程序的内存状况,HotSpot虚拟机并不是永远要求对象的年龄必须达到-XX:MaxTenuringThreshold才能晋升老年代,如果在 Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。
  • 空间分配担保
    假如在Young GC之后,新生代仍然有大量对象存活,就需要老年代进行分配担保,把Survivor无法容纳的对象直接送入老年代。

三、类加载过程

1、类的生命周期

在这里插入图片描述

2、类加载过程

在这里插入图片描述
一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去自定义类加载器去控制字节流的获取方式(重写一个类加载器的loadclass()方法)。数组类型不通过类加载器创建,它由Java虚拟机直接创建。
所有的类都由类加载器加载,加载的作用就是将.class文件加载到内存。

1、加载

在这里插入图片描述

2、验证

在这里插入图片描述

3、准备

在这里插入图片描述

4、解析

在这里插入图片描述

5、初始化

在这里插入图片描述

Q:初始化开始的时机

在这里插入图片描述

6、卸载

在这里插入图片描述

注意: 接口加载过程与类加载过程稍有不同。当一个类在初始化时,要求其父类全部都已经初始化过了,但是一个接口在初始化时,并不要求其父接口全部都完成了初始化,当真正用到父接口的时候才会初始化。

3、Java中的类加载器

JVM类加载器分为两类:JVM自带的类加载器和自定义类加载器。
在这里插入图片描述

Q:为什么要自定义类加载器?

① 隔离加载类;② 修改类加载的方式;③ 扩展加载源;④ 防止源码泄漏。

Q:如何实现自定义类加载器?

继承抽象类java.lang.ClassLoader类的方式,实现自己的类加载器。

4、双亲委派模型

每一个类都有一个对应它的类加载器。系统中的ClassLoader在协同工作的时候会默认使用双亲委派模型。即在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载。加载的时候,首先会把该请求委派给父类加载器的loadClass()处理,因此所有的请求最终都应该传送到顶层的启动类加载器BootstrapClassLoader中。当父类加载器无法处理时,才由自己来处理。当父类加载器为null时,会使用启动类加载器BootstrapClassLoader作为父类加载器。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Q:双亲委派模型实现步骤?

①首先判断该类是否已经被加载;
②该类未被加载,同时父类不为空,交给父类加载;
③如果父类为空,交给启动类加载器Bootstrap ClassLoader加载;
④如果类还是无法被加载到,则触发findclass,抛出ClassNotFoundException(findclass这个方法当前只有一个语句,就是抛出ClassNotFoundException),如果想自己实现类加载器的话,可以继承ClassLoader后重写findclass方法,加载对应的类)。

Q:双亲委派模型的好处?

双亲委派模型 保证了Java程序的稳定运行,可以避免类的重复加载(JVM区分不同类的方式不仅仅根据类名,相同的类文件被不同的类加载器加载产生的是两个不同的类★★★),也保证了Java的核心API不被篡改。如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 java.lang.Object类的话,那么程序运行的时候,系统就会出现多个不同的Object类。

Q:如何判断两个Class对象是否是一个类?

在JVM中表示两个Class对象是否为同一个类存在两个必要条件:

  • 类的 完整类名必须一致 ,包括包名。
  • 加载这个类的类加载器 ClassLoader (指ClassLoader实例对象)必须相同。

换句话说,在JVM中,即使这两个类对象(class对象)来源同一个Class文件,被同一个虚拟机所加载,但只要加载它们的ClassLoader实例对象不同,那么这两个类对象也是不相等的

Q:不想使用双亲委派模型怎么解决?

自定义加载器的话,需要继承ClassLoader。如果我们 不想打破双亲委派模型 ,就重写ClassLoader类中的findclass()方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。但是,如果 想打破双亲委派模型 则需要重写loadClass()方法

Q:3次打破双亲委派机制的案例?
  • 第一次破坏
    第一次被破坏发生在双亲委派模型出现之前——即JDK 1.2之前。
  • 第二次破坏
    第二次被破坏是由这个模型自身的缺陷导致的,如果有基础类型又要调用回用户的代码,那该怎么办呢?如JDBC。
  • 第三次破坏
    第三次被破坏是由于用户对程序动态性的追求而导致的,例如代码热替换(Hot Swap)、模块热部署(Hot Deployment)等。
Q:如何实现热部署?

想要实现热部署可以分以下三个步骤:

  1. 销毁原来的自定义ClassLoader
  2. 更新class类文件
  3. 创建新的ClassLoader去加载更新后的class类文件。
    到此,一个热部署的功能就这样实现了。

5、Tomcat的类加载机制?

在这里插入图片描述

Tomcat破坏了双亲委派原则,提供隔离的机制,为每个web容器单独提供一个WebAppClassLoader加载器。每一个WebAppClassLoader负责加载本身的目录下的class文件,加载不到时再交给CommonClassLoader加载,这和双亲委派刚好相反。

四、JVM调优参数

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、JVM调优

1、常用的命令行性能监控和故障处理工具?

  • 操作系统工具
    top:显示系统整体资源使用情况。
    vmstat:监控内存和 CPU。
    iostat:监控 IO 使用。
    netstat:监控网络使用。
  • JDK性能监控工具
    jps:虚拟机进程查看。
    jstat:虚拟机运行时信息查看。
    jinfo:虚拟机配置查看。
    jmap:内存映像(导出)。
    jhat:堆转储快照分析。
    jstack:Java 堆栈跟踪。
    jcmd:实现上面除了jstat外所有命令的功能。

2、JVM可视化的性能监控和故障处理工具有?

JConsole、VisualVM、Java Mission Control(前3个为JDK自带)、MAT(Java堆内存分析工具)、GChisto(GC日志分析工具)、GCViewer(GC日志分析工具)、JProfiler(性能分析工具)、arthas(阿里开源诊断工具)

3、线上服务CPU占用过高怎么排查?

问题分析:CPU高一定是某个程序长期占用了CPU资源。
在这里插入图片描述

  1. 先找出是哪个进程占用CPU高:top 列出系统各个进程的资源占用情况。
  2. 然后根据找到对应进程里哪个线程占用CPU高:top -Hp 进程id 列出对应进程里面的线程占用资源情况。
  3. 找到对应线程id后,再打印出对应线程的堆栈信息:
    printf "%x\n" PID 把线程id转换为16进制。
    jstack PID 打印出进程的所有线程信息,从打印出来的线程信息中找到上一步转换为16进制的线程id对应的线程信息。
  4. 最后根据线程的堆栈信息定位到具体业务方法,从代码逻辑中找到问题所在。
    查看是否有线程长时间的watting或blocked,如果线程长期处于watting状态下,关注watting on xxxxxx,说明线程在等待这把锁,然后根据锁的地址找到持有锁的线程。

4、内存飙升怎么排查?

分析:内存飚高如果是发生在java进程上,一般是因为创建了大量对象所导致,持续飚高说明垃圾回收跟不上对象创建的速度,或者内存泄露导致对象无法回收。

  1. 先观察垃圾回收的情况
    jstat -gc PID 1000 查看GC次数、时间等信息,每隔一秒打印一次。
    jmap -histo PID | head -20 查看堆内存占用空间最大的前20个对象类型,可初步查看是哪个对象占用了内存。
    如果每次GC次数频繁,而且每次回收的内存空间也正常,那说明是因为对象创建速度快导致内存一直占用很高;如果每次回收的内存非常少,那么很可能是因为内存泄露导致内存一直无法被回收。
  2. 导出堆内存文件快照
    jmap -dump:live,format=b,file=/home/myheapdump.hprof PID dump 堆内存信息到文件。
  3. 使用visualVM对dump文件进行离线分析,找到占用内存高的对象,再找到创建该对象的业务代码位置,从代码和业务场景中定位具体问题。

5、频繁的年轻代垃圾回收怎么办?

优化Minor GC频繁问题:通常情况下,由于新生代空间较小,Eden区很快被填满,就会导致频繁Minor GC,因此可以通过 增大新生代空间-Xmn来降低 Minor GC的频率

6、频繁的整堆垃圾回收(full GC)怎么办?

Full GC的排查思路大概如下:
1. 清楚从程序角度,有哪些原因导致full GC?
· 大对象:系统一次性加载了过多数据到内存中(比如SQL查询未做分页),导致大对象进入了老年代。
· 内存泄漏:频繁创建了大量对象,但是无法被回收(比如IO对象使用完后未调用close方法释放资源),先引发full GC,最后导致OOM.
· 程序频繁生成一些长生命周期的对象,当这些对象的存活年龄超过分代年龄时便会进入老年代,最后引发full GC。
· 程序BUG
· 代码中显式调用了gc方法,包括自己的代码甚至框架中的代码。
· JVM参数设置问题:包括总内存大小、新生代和老年代的大小、Eden区和S区的大小、元空间大小、垃圾回收算法等等。

2. 清楚排查问题时能使用哪些工具?
JDK 的自带工具,包括jmap、jstat等常用命令:

# 查看堆内存各区域的使用率以及GC情况
jstat -gcutil -h20 pid 1000
# 查看堆内存中的存活对象,并按空间排序
jmap -histo pid | head -n20
# dump堆内存文件
jmap -dump:format=b,file=heap pid

可视化的堆内存分析工具:JVisualVM、MAT等

3. 排查指南
· 查看监控,以了解出现问题的时间点以及当前full GC的频率(可对比正常情况看频率是否正常)
· 了解该时间点之前有没有程序上线、基础组件升级等情况。
· 了解JVM的参数设置,包括:堆空间各个区域的大小设置,新生代和老年代分别采用了哪些垃圾收集器,然后分析JVM参数设置是否合理。
· 再对步骤1中列出的可能原因做排除法,其中元空间被打满、内存泄漏、代码显式调用gc方法比较容易排查。
· 针对大对象或者长生命周期对象导致的full GC,可通过 jmap -histo 命令并结合dump堆内存文件作进一步分析,需要先定位到可疑对象。
· 通过可疑对象定位到具体代码再次分析,这时候要结合GC原理和JVM参数设置,弄清楚可疑对象是否满足了进入到老年代的条件才能下结论。

7、内存泄漏和内存溢出如何排查?

内存泄漏是内在病源,外在病症表现可能有:(内存泄漏可能导致内存溢出,排查步骤和内存泄漏类似)

  • 应用程序长时间连续运行时性能严重下降。
  • CPU使用率飙升,甚至到100% 。
  • 频繁Full GC,各种报警,例如接口超时报警等。
  • 应用程序抛出OutOfMemoryError错误。
  • 应用程序偶尔会耗尽连接对象。

严重内存泄漏往往伴随频繁的Full GC,所以分析排查内存泄漏问题首先还得从查看Full GC入手。主要有以下操作步骤:

  1. 使用 jps 查看运行的 Java 进程 ID
  2. 使用 top -p [pid] 查看进程使用 CPU 和 MEM 的情况
  3. 使用 top -Hp [pid] 查看进程下的所有线程占 CPU 和 MEM 的情况
  4. 将线程 ID 转换为 16 进制:printf "%x\n" [pid],输出的值就是线程栈信息中的 nid。
  5. 抓取线程栈:jstack 29452 > 29452.txt,可以多抓几次做个对比。
  6. 使用 jstat -gcutil [pid] 5000 10 每隔 5 秒输出 GC 信息,输出 10 次,查看 YGC 和 Full GC 次数。通常会出现 YGC 不增加或增加缓慢,而 Full GC 增加很快。或使用 jstat -gccause [pid] 5000 ,同样是输出 GC 摘要信息。或使用 jmap -heap [pid] 查看堆的摘要信息,关注老年代内存使用是否达到阀值,若达到阀值就会执行 Full GC。
  7. 如果发现 Full GC 次数太多,就很大概率存在内存泄漏了
  8. 使用 jmap -histo:live [pid] 输出每个类的对象数量,内存大小(字节单位)及全限定类名。
  9. 生成 dump 文件,借助工具分析哪个对象非常多,基本就能定位到问题在那了。
  10. dump 文件分析
    可以使用 jhat 命令分析:jhat -port 8000 29471.dump,浏览器访问 jhat 服务,端口是 8000。或使用第三方式具分析的,如 JProfiler 也是个图形化工具,GCViewer 工具。Eclipse 或以使用 MAT 工具查看。或使用在线分析平台 GCEasy。
  11. 在 dump 文析结果中查找存在大量的对象,再查对其的引用。

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

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

相关文章

STM32CubeIDE下载安装

一,下载安装。 官方下载地址: STM32CubeIDE - STM32的集成开发环境 - STMicroelectronics 下载需要注册账号,或者登记信息。 安装过程很简单,默认next就行,不过注意安装文件目录不要有中文,不然会报错&a…

java计算机毕业设计ssm美妆产品进销存管理系统

项目介绍 随着经济的发展和信息技术的普及,国内许多企业都面临了重大的挑战。企业的管理流程、战略规划如果不能进行调整,极有可能面临淘汰的风险。特别是美妆企业,面对大量的美妆产品和进销售管理,如果不使用信息系统进行有效的管理和利用,那就会阻碍企业的发展,使企业在市场…

学生dreamweaver网页设计作业成品___辅导网站( 4页 登录注册 轮播图)

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | | HTML期末大学生网页设计作业,Web大学生网页 HTML:结构 CSS:样式 在操作方面上运用了html5和css3, 采…

高性能 MySQL - 第六章 查询性能优化

最近阅读MySQL高性能,略有收获,好记忆不如烂笔头,记录一下。本期笔记主要是围绕高性能MySQL第六章查询性能优化。 整体结构 重点、亮点内容摘抄 第六章 查询性能优化 查询优化、索引优化、库表结构优化需要齐头并进,一个不落。在…

nodejs express 的基本使用

测试需要快速过一遍express的基本使用方法 直接安装express使用 express和koa的区别](https://zhuanlan.zhihu.com/p/372128788)egg.js企业级开发框架 npm install exress --save可以使用express-generator生成项目框架 $ npx express-generatorwarning: the default view …

call()、apply()、bind() 区别、使用场景、实现方式

目录 1. call()、apply()、bind() 三者区别 1.1 作用 1.2 参数 1.3 执行时机 2. call()、apply() 使用场景 2.1 使用 Array.prototype.push.apply(arr1, arr2) 合并两个数组 2.1.1 原理(看了手写方法,或许会更有助于理解) 2.1.2 如何…

微电网两阶段鲁棒优化(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

LeetCode刷题复盘笔记—一文搞懂62. 不同路径 63. 不同路径 II(动态规划系列第三篇)

今日主要总结一下动态规划的两道题目,62. 不同路径 && 63. 不同路径 II 题目一:62. 不同路径 题目描述: 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或…

HTML CSS 网页设计作业「体育小站」(梅西足球 6页 )

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 校园篮球网页设计 | 足球体育运动 | 体育游泳运动 | 兵乓球 | 网球 | 等网站的设计与制作| HTML期末大学生网页设计作业,Web大学生网页 HT…

JavaScript之PC端网页特效(55th)

在前面学习了JS基础、DOM 和 BOM 的基本操作后,这部分主要学习这些知识的拓展应用 1、元素偏移量 offset 系列 1、offset 概述 offset 翻译过来就是偏移量,我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.7 SpringBoot 操作 Redis 客户端实现技术切换【jedis】

SpringBoot 【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.7 SpringBoot 操作 Redis 客户端实现技术切换【je…

数据结构实验教程-第二套

5.一棵左子树为空的二叉树在先序线索化后,其中空的链域的个数是 a.不确定 b.0 c.1 d.2在先序线索化之后,相当于只有开始节点没有前驱,最后的节点没有后继,因此空链域只有2个,分别是开始节点的左孩子和最后节…

【笔试题】【day23】

文章目录第一题(二叉树度结点的计算)第二题(平衡查找二叉树)第三题(堆的插入)第四题(哈希表的查找)第五题(大数排序)第一题(二叉树度结点的计算&a…

功能测试

功能测试 按照是否覆盖源代码 黑盒测试(输入和输出) 白盒测试(代码内部实现逻辑) 灰盒测试(输入输出和代码逻辑) 介于白盒测试和黑盒测试之间的测试,多用于集成阶段,不仅关注输入输…

智能制造与数字化工厂

智能制造是基于新一代信息技术,贯穿设计、生产、管理、服务等制造活动各个环节,具有信息深度自感知、智慧优化自决策、精准控制自执行等功能的先进制造过程、系统与模式的总称。具有以智能工厂为载体,以关键制造环节智能化为核心,…

通信用多模光纤主要有哪些类型?OM1~OM5有什么区别

1 前言 根据光纤内光信号传输模式的不同,光纤可分为单模光纤和多模光纤,见《常用通信光纤是如何分类的》一文。 在传送网和有线接入网中,我们接触到的光纤类型主要有:G.652、G.654和G.657,这些都是单模光纤。多模光纤…

Linux 系统启动过程

linux启动时我们会看到许多启动信息。 Linux系统的启动过程并不是大家想象中的那么复杂,其过程可以分为5个阶段: 内核的引导。运行 init。系统初始化。建立终端 。用户登录系统。init程序的类型: SysV: init, CentOS 5之前, 配置文件&#…

通关算法题之 ⌈二叉树⌋ 上

二叉树深度 104、求二叉树最大深度 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数,叶子节点是指没有子节点的节点。 示例: 给定二叉树[3,9,20,null,null,15,7], 3/ \9 20/ \15 7返回它的最大深度 3。 解法一:递…

Linux进阶-Shell编程

目录 定义变量: 使用变量: 将命令的结果赋值给变量: 删除变量:unset 退出当前进程:exit 读取从键盘输入的数据 :read 对整数进行数字运算:(()) 逻辑与或: 检测某个条件是否成…

Qt QSqlQueryModel详解

1.功能概述 QSqlQueryModel是QSqlTableModel的父类。QSqlQueryModel封装了执行SELECT语句从数据库查询数据的功能,但是QSqlQueryModel只能作为只读数据源使用,不可以编辑数据。 2.常用API void clear() //清除数据模型,释放所有获得的数据…