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

【JVM】常见面试题

🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈

在这里插入图片描述

文章目录

  • 1. JVM 中的内存区域划分
  • 2. JVM 的类加载机制
    • 2.1 加载(Loading)
    • ✨双亲委派模型
    • 2.2 验证(Verification)
    • 2.3 准备(Preparation)
    • 2.4 解析(Resolution)
    • 2.5 初始化(Initialization)
  • 3. JVM 中的垃圾回收
    • 3.1 找 —— 谁是垃圾
      • 3.1.1 引用计数法
      • 3.1.2 可达性分析
    • 3.2 释放 —— 把垃圾对象的内存给释放掉
      • 3.2.1 标记清除算法
      • 3.2.2 复制算法
      • 3.2.3 标记整理算法
      • 3.2.4 分代算法

本期内容主要介绍有关 JVM 相关知识,这里只是简单介绍,JVM 的知识有很多,具体可看参考书《深入理解Java虚拟机》,作为一名普通的 Java 程序猿,日常开发中的时候几乎是涉及不到 JVM 相关内容哒~

JVM 设计的初心就是为了让 Java 程序猿感知不到系统层面的一些内容,程序猿只需关注业务逻辑,不要关注底层的实现细节!!!

JVM 里的内容是非常多的,需要研究 JVM 的源代码,其源代码由 C++ 编写,本期内容针对以下三个方面进行介绍 JVM,我们一起来看看吧~

1. JVM 中的内存区域划分

JVM 其实是一个 Java 进程,Java 进程会从操作系统这里申请一大块内存区域给 Java 代码使用,对这块内存区域进一步划分为几个最核心的内存区域,给出不同的用途:

  1. :存放 new 出来的对象(成员变量)
  2. :存放维护方法之间的调用关系(也会存一些局部变量)
  3. 方法区/元数据区:存放类加载之后的类对象(这里的类对象就包含了静态变量)
    (方法区是旧的叫法,最新叫法为元数据区)

类对象
类对象是什么?即类加载之后的东西,本来一个类是.class 文件,把它加载在内存里,需要有一个数据结构来表示它,可以通过类名.class,比如 Test.class 来获取 Test 类对象

这里的主要考点就是给一段代码,判断某个变量处于内存的哪个区域~
规则】是看这个变量的形态!比如是局部变量还是成员变量,还是静态变量呢?如果是局部变量就存放在栈上,如果是成员变量就存放在堆上,如果是静态变量就存放在方法区内~
注意】和变量的类型是无关的!!! 并不是内置类型变量就在栈上,引用类型变量就在堆上

举一个具体的栗子,代码如下:

// Test类
class Test {
}void func() {Test t  = new Test();
}

在这里插入图片描述

分析如下:t 本身是一个引用类型,它是一个局部变量,因此存放在栈上,而 new 出来的对象,对象本身是成员变量,存放在堆上
在这里插入图片描述
以下是 JVM 的执行流程,下面系统重点介绍 JVM 运行时数据区,JVM 运行时数据区域也叫内存布局,如图:

在这里插入图片描述
这里需要注意
1)堆和方法区在一个 JVM 进程中,只有一份,但是(包括虚拟机栈与本地方法栈)和程序计数器存在多份,每一个线程都有一份!
2)JVM 的线程和操作系统的线程是一一对应的关系,每次在 Java 代码中创建线程,必然会在系统中有一个对应的线程

JVM 内存划分区域:

  • 本地方法栈:是给 JVM 内部的本地方法使用的,其中 JVM 内部通过 C++ 代码实现的方法
  • 虚拟机栈:是给 Java 代码使用的,它的生命周期和线程一样,当线程执行一个方法的时候,会创建一个对应的栈帧,用于存储局部变量等信息,然后栈帧被压入栈中,当方法执行完毕后,栈帧会从栈中移除
  • 程序计数器:也称 PC 计数器,用途是记录当前程序指定到哪个指令了,是一个简单的 long 类型的变量存了一个内存地址,内存地址就是下一个要执行的字节码所在的地址
  • :堆是 JVM 中最大的一块内存区域,被所有线程共享,在 JVM 启动时创建,用来存储对象
  • 方法区:方法区也是所有线程共享的,用于存储类加载之后的对象

2. JVM 的类加载机制

类加载就是把 .class 文件加载到内存中,得到类对象的这样一个过程,程序想要运行就需要把依赖的"指令和数据"加载到内存中

类加载的步骤其实非常复杂,本期内容开头提到的书把类加载的过程总结为 5 个词,也是 Java 虚拟机规范,分为:加载 —— 验证 —— 准备 —— 解析 —— 初始化,如下图:
在这里插入图片描述
下面具体介绍这五个步骤:

2.1 加载(Loading)

加载】加载阶段就是找到 .class 文件,并且读文件的内容

在加载(Loading)阶段,Java虚拟机需要完成以下三件事情:

  • 通过类名.class 获取二进制字节流
  • 把这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  • 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口

注意加载是类加载的一个阶段,加载是加载,类加载是类加载,注意区分两者~

如何找到这个 .class 文件呢?这里会涉及到一个经典的考点:双亲委派模型

✨双亲委派模型

在介绍双亲委派模型之前,需要先知道 JVM 加载类时需要用到一组特殊的模块 —— 类加载器

类加载器用于动态加载 Java 类到 Java 虚拟机中,主要有以下 4 种类型类加载器,其中在 JVM 中内置了三个类加载器,即如下的前三个:

  • 启动类加载器(Bootstrap ClassLoader):负责加载 Java 标准库中的类
  • 扩展类加载器(Extension ClassLoader):负责加载一些非标准库但是由 Sun / Oracle 扩展的库的类
  • 应用程序类加载器(Application ClassLoader):负责加载项目中自己写的类以及第三方库中的类
  • 用户自定义类加载器(User-Defined ClassLoader):可以通过继承 java.lang。ClassLoader 类来创建自己的类加载器

类加载中最关键的一个考点是双亲委派模型双亲委派模型做的工作就是在类加载的第一个阶段 —— 加载阶段,找 .class 文件这个过程 ~

双亲委派模型
这种模型指的是,一个类加载器在尝试加载某个类的时候,首先会将加载任务委托为其父类加载器去完成,只有当父类加载器无法完成这个加载请求,即父类加载器找不到指定的类,子类加载器才会尝试去自己加载这个类

在这里插入图片描述
这里仅考虑在 JVM 中内置的三个类加载器,具体流程如下:

  • 当一个类加载器需要加载某个类的时候,它首先会请求其父类加载器加载这个类
  • Bootstrap ClassLoader 启动类加载器,没有父加载器了,因此只能自己来搜索自己负责的片区,如果搜索到,就直接进行后续加载步骤,如果没有搜索到,再交给孩子处理
  • Extension ClassLoader 扩展类加载器,收到了父亲的反馈,自己来找,如果搜索到,就直接进行后续加载步骤,如果没有搜索到,再交给孩子处理
  • Application ClassLoader 应用程序类加载器收到了父亲的反馈,自己来找,如果搜索到,就直接进行后续加载步骤,如果没有搜索到,再交给孩子处理,但是这里没有孩子了,就会抛出一个 ClassNotFoundException

这个流程在日常中也经常存在,把 Bootstrap 想象成公司老板,Extension 想象成主管,Application 想象成基层员工!

双亲委派模型的优点

  1. 避免重复加载类:比如 A 类和 B 类都有共同的父类 C 类,当 A 启动时就会将 C 类加载起来,在 B 类进行加载时就不需要在重复加载 C 类

  2. 保证安全性:使用双亲委派模型也可以保证 Java 的核心 API 不被篡改

注意
1)双亲委派模型也是可以打破的,比如自己实现的类加载器,可以继续遵守双亲委派模型,也可以不遵守,比如 Tomcat 里针对 webapp 的类加载器就没有遵守双亲委派模型
2)反射和类加载的关系是,类加载得到的类对象是反射机制的前提条件

2.2 验证(Verification)

验证.class 文件有明确的数据格式(二进制),该阶段是确保.class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全

验证选项有很多,比如有:

  • 文件格式验证
  • 字节码验证
  • 符号引用验证…

打开这个官方文档,可以查看虚拟机规范
在这里插入图片描述
这里找的是 Java SE 8 早一点版本的虚拟机规范,在第 4 章可以看到 .class 文件有明确的数据格式,如下:

在这里插入图片描述

2.3 准备(Preparation)

准备】给类对象分配内存空间,未初始化的空间,即初始值为数据类型的默认初始值,简单认为内存空间中的数据全为 0,类对象中的静态成员变量等全为 0

2.4 解析(Resolution)

解析】针对字符串常量进行初始化,即虚拟机将常量池中的符号引用替换为直接引用的过程

解释说明:
字符串常量在 .class 文件中就存在了,但是它们只是知道彼此之间的相对位置,即偏移量,并不知道自己在内存中的实际地址,此时的字符串常量就是符号引用,真正加载到内存中,就是把字符串常量填充到内存的特定的地址上,字符串常量之间的相对位置还是一样的,但是这些字符串常量之间相对位置仍然是一样的,但是这些字符串有了真正的内存地址,此时的字符串常量就是直接引用了,即 Java 中的普通引用

举个例子,更能理解:
比如小丁和小万是好朋友,大课间从教室去操场做操,先在教室门口排好队,由体育委员带头过去,但是走着走着队伍就变形了,小丁就需要走位,保持和小万是同行的,这样小丁和小万一直走在一块,相对位置不变,到达操场后,小丁和小万还是在一块,此时两个好朋友就挨着了,一起做操了~ 在到达操场前,小丁和小万并不知道待会在操场上站在哪里,但是两个人的相对距离彼此清楚的,真正到达操场后,小丁和小万确定了自己的站位,位置就固定了,此时两个人还是挨着的,相对位置不变~ 这就类比符号引用替换为直接引用的过程

2.5 初始化(Initialization)

初始化针对类对象进行初始化,比如初始化静态成员,执行静态代码,如果这个类还有父类,需要先把父类加载出来


类加载这个动作,什么时候会触发呢?

并不是 JVM 一启动,就把所有的 .class 都加载了,坚持着 “非必要,不加载” 的原则,即需要的时候再加载~

什么时候是必要?

  • 创建了这个类的实例
  • 使用了这个类的静态方法/静态属性
  • 使用子类,会触发父类的加载

3. JVM 中的垃圾回收

含义
垃圾回收(Garbage Collection,GC),从字面上来看,就是释放垃圾占用的空间,防止内存爆掉,JVM 垃圾回收是帮助程序员自动释放掉内存的~

在 C 语言中,malloc 的内存必须手动 free,否则就容易出现内存泄露问题,即光申请内存不进行释放,内存逐渐用完,导致程序崩溃,Java 等后续的编程语言,引入 GC 来解决上述问题,能够有效的减少内存泄露的出现概率

作用
实际上,内存的释放是一个比较纠结的事情:

申请的时机是明确的 —— 使用到了就必须申请
释放的时机是模糊的 —— 彻底不使用了才能释放(如果还没使用完就释放,就会导致一些问题)

C/C++ 的做法是完全让程序员来决定,特别依赖程序员的水平,Java 通过 JVM 自动判定,基于一系列策略,就可以提高释放时机的准确性,但是同时也会付出一些代价

JVM 中的垃圾回收的对象
Q:JVM 中的内存有好几个区域,是释放哪个部分的空间呢?
A:堆,new 出来的对象

程序计数器就是一个单纯存地址的整数,不需要释放,随着线程一起销毁,栈也是随着线程一起销毁,方法的局部变量也就自然随着出栈操作销毁了,方法区/元数据区存的类对象,很少会将其"卸载"掉

GC 主要分为以下两个阶段:

这里涉及到垃圾回收算法,基本的思想方法,不代表 JVM 真实的实现方式,JVM 的真实实现方式,是基于这些思想方法,但是同时又做出很多细节上的调整和优化~

3.1 找 —— 谁是垃圾

如何确认垃圾】 一个对象,如果后续不再用了,就可以认为是垃圾

在 Java 中使用一个对象,只能通过引用,如下:
如果一个对象没有引用指向它,此时这个对象一定是无法被使用的,被视为垃圾
如果一个对象已经不想用了,但是这个引用可能还指向着(这里就不当做垃圾处理)

Java 中只是单纯通过引用有没有指向这个操作,来判定是否为垃圾,Java 中对于垃圾对象的识别是比较保守的,最大程度上避免“误杀”,释放不及时是小事,误杀是大事!

如何找垃圾
具体来说 Java 如何知道一个对象是否有指向引用呢?有两种算法:

3.1.1 引用计数法

引用计数法】给对象安排一个额外空间,保存一个整数,表示该对象有几个引用指向
(Java 实际上没有使用这个方案,Python、PHP采取该方案)

图解如下:
在这里插入图片描述

随着引用的增加,计数器就增加,引用销毁,计数器就减少,当计数器为0的时候,则认为该对象没有引用了,就是垃圾

注意是每个对象都有一个单独的计数器,不是每个类都有一个

但是这会带来一个问题:

在这里插入图片描述

此时,如果 a 和 b 销毁了,这个时候两个对象的引用计数各自减1,它们的计数器值为 2 - 1,为 1,这个时候这两个对象引用计数不是 0,不能作为垃圾,而这两个对象却无法使用了,陷入一个逻辑上的循环

优点】实现简单
缺点】1. 浪费空间 2.存在循环引用的情况,会导致引用计数的判定逻辑出错

3.1.2 可达性分析

可达性分析
把对象之间的引用关系,理解成了一个树形结构,从一些特殊的起点出发,进行遍历,只要能遍历访问到的对象,就是"可达"的,再把"不可达的"当做垃圾即可
(Java没有使用引用计数,采用了可达性分析)
在这里插入图片描述

可达性分析的关键要点,就是进行上述遍历,需要有"起点",可以作为起点的:

  • 栈上的局部变量,每个栈上的局部变量都是起点
  • 常量池中引用的对象
  • 方法区中静态成员引用的对象

可达性分析,简单来说,就是从所有的 gcroots 的起点出发,通过遍历,看看该对象又通过引用能访问哪些对象,把所有可以访问的对象都遍历一遍,遍历的同时将对象标记成"可达",剩下的就"不可达"

优点】克服了引用计数的两个缺点
缺点
1)消耗更多的时间,因此某个对象成为了垃圾,不一定能及时发现,因为扫描的过程中,需要消耗时间
2)在进行可达性分析的时候,遍历过程中,一旦这个过程中,当前代码的对象引用关系发生变化,此时就更加麻烦, 因此,为更准确完成这个过程,需要让其它业务线程暂停工作!

3.2 释放 —— 把垃圾对象的内存给释放掉

通过上述分析,将可回收的对象标记出来了,标记出来之后,就可以进行垃圾回收操作了,如何进行高效的垃圾回收呢?以下介绍 4 种算法:

3.2.1 标记清除算法

标记清除算法】直接把垃圾对象内存释放掉

在这里插入图片描述

优点】实现简单
缺点】这种方式会产生内存碎片,申请空间都是申请"整块的连续的空间",比如总的空闲空间可能超过 1G,但是这些空闲的空间都是离散的、独立的,可能想申请到 500M 空间都申请不到~

3.2.2 复制算法

复制算法】由上述标记清理算法演化而来,它将内存容量等大小分为两块,每次只使用其中的一块,把不是垃圾的对象,拷贝到另一边,再整个释放这个垃圾区域

在这里插入图片描述
优点】解决内存碎片问题
缺点】空间利用率低,因为复制算法每次只能使用一半的内存,如果当前对象大部分都是要保留的,垃圾很少,则复制成本较高

3.2.3 标记整理算法

标记整理算法】与标记清除法一样,但是不是直接清理可回收对象,先有一个移动的的过程,将所有存活的对象都向一端移动,再清理掉边界以外的内存区域
在这里插入图片描述
优点】解决内存碎片问题,比复制算法空间利用率高
缺点】类似于顺序表有一个搬运的过程,因为有局部对象的移动,开销比较大,效率不是很高

3.2.4 分代算法

实际上,JVM 的实现思路,结合了上述几种思想方法,针对不同的情况使用不同的策略,到达取长补短的效果,下面具体介绍给算法 —— 分代回收算法

分代算法】根据对象存活周期不同将内存划分为几块,一般将 Java 堆 分为新生代和老年代,根据各个年代选择适合的垃圾收集算法

给对象设定了"年龄",描述这个对象存在的时间,如果一个对象刚诞生,认为是 0 岁,每次经过一轮扫描,即可达性分析,没有被标记成垃圾,这个时候对象就涨一岁,通过年龄来区分这个对象的存活时间,由经验规律可以得到:如果一个对象存活时间很长,它将可以继续存在很长时间

由于新生代存放的大部分数据都是朝生夕死的,因此,新生代使用效率高的复制算法,而老生代使用标记清除/标记清理算法(哪个好使用哪个)

在这里插入图片描述
具体过程如下:
1)新创建的对象放到伊甸区,当垃圾回收扫描到伊甸区后,绝大部分的对象都会在 GC 中被干掉,大部分对象是活不过一岁的,由经验规律得知;
2)如果伊甸区的对象,撑过第一轮 GC,就会通过复制算法,把存活的对象拷贝到生存区
3)当这个对象在生存区,撑过多轮 GC 后,年龄增长到一定程度,就会通过复制算法拷贝到老年代
4)进入老年代的对象,年龄都较大,再消亡的概率较低,针对老年代的 GC 扫描频次就会降低,如果发现老年代中某个对象是垃圾,可以使用标记清除/标记清理算法,进行清除

垃圾收集器是具体的实现方式,具体实现往往是基于上述思想方法做出一些优化和改进,包含更多的实现字节,Java 版本的变更,垃圾回收器也在不断变化~

✨✨✨本期内容到此结束啦~

相关文章:

【JVM】常见面试题

🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. JVM 中的内存区域划分2. JVM 的类加载机制2.1 加载(Loading)✨双亲委派模型2.2 验证(Verification)2.3 准…...

0805作业+梳理

一、作业&#xff1a; 代码&#xff1a; create.c #include<myhead.h> int main(int argc, const char *argv[]) {//创建一个有名管道文件if(mkfifo("./linux",0664)-1){perror("mkfifo linux error");return -1;}getchar();system("rm linux…...

Java高并发编程详解教程(对高并发更深一层的领悟和体会 电子版)

前言 第一部分主要阐述Thread的基础知识&#xff0c;详细介绍线程的API使用、线程安全、线程间数据通信以及如何保护共享资源等内容&#xff0c;它是深入学习多线程内容的基础。 在第二部分中之所以引人 ClassLoader&#xff0c;是因为 ClassLoader 与线程不无关系&#xff0…...

字符串中的第一个唯一字符

给定一个字符串 s &#xff0c;找到 它的第一个不重复的字符&#xff0c;并返回它的索引 。如果不存在&#xff0c;则返回 -1 。 s 只包含小写字母 示例 1&#xff1a; 输入: s "leetcode" 输出: 0示例 2: 输入: s "loveleetcode" 输出: 2示例 3: 输…...

leetcode数论(​3044. 出现频率最高的质数)

前言 经过前期的基础训练以及部分实战练习&#xff0c;粗略掌握了各种题型的解题思路。现阶段开始专项练习。 描述 给你一个大小为 m x n 、下标从 0 开始的二维矩阵 mat 。在每个单元格&#xff0c;你可以按以下方式生成数字&#xff1a; 最多有 8 条路径可以选择&#xff1…...

70.加载功能菜单功能设计

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;易道云信息技术研究院 上一个内容&#xff1a;69.搭建分析工具界面 以 69.搭建分析工具界面 它的代码为基础进行修改 效果图&#xf…...

在线Banner设计工具大比拼:谁更胜一筹

在数字营销的时代&#xff0c;一个吸引眼球的 Banner 广告是吸引潜在客户、提高品牌知名度的关键。为了帮助营销人员和设计师快速创建专业的 Banner 广告&#xff0c;市面上出现了多种易于使用的 Banner 设计工具。本文将介绍几个受欢迎的 Banner 设计工具&#xff0c;包括即时…...

C++ STL copy, move 用法

一&#xff1a;功能 正向&#xff08;从前向后的顺序&#xff09;拷贝/移动操作&#xff0c;将一个容器元素拷贝/移动到另一容器中。 二&#xff1a;用法 #include <iostream> #include <vector> #include <algorithm>int main() {std::vector<std::str…...

MoonBit 周报 Vol.52:增加类型别名的支持、错误类型声明方式说明、MoonBit AI 支持生成文档等!

weekly 2024-08-05 MoonBit更新 JSON字面量支持array spread。 let xs: Array[json.JsonValue] [1, 2, 3, 4] let _: json.JsonValue [1, ..xs]增加了类型别名的支持&#xff0c;主要是为了渐进式代码重构和迁移&#xff0c;而不是某种给类型简短名字的机制。例如&#xf…...

Android开发之事件分发

#来自ウルトラマンゼロ&#xff08;哉阿斯&#xff09; 1 Activity 构成 平常布局展示在ContentView中。 2 事件分发 事件分发的本质其实就是把事件&#xff08;Touch&#xff09;封装成 MotionEvent 类&#xff0c;然后传递给 View 的层级处理。 MotionEvent 事件类型主要有…...

PyTorch深度学习实战(2)——PyTorch快速入门

PyTorch的简洁设计使得它易于入门&#xff0c;在深入介绍PyTorch之前&#xff0c;本文先介绍一些PyTorch的基础知识&#xff0c;以便读者能够对PyTorch有一个大致的了解&#xff0c;并能够用PyTorch搭建一个简单的神经网络。 1 Tensor Tensor是PyTorch中最重要的数据结构&#…...

ServletConfig、ServletContext超详细讲解

文章目录 前言一、ServletConfig的使用1.ServletConfig定义2.ServletConfig的API3.ServletConfig的测试代码&#xff1a; 二、 ServletContext的使用1.ServletContext定义2.ServletContext如何用3. ServletContext其他重要API 总结 前言 ServletConfig接口代表了Servlet的配置信…...

【文献阅读】GraphAny: A Foundation Model for Node Classification on Any Graph

Abstract 可以执行任何新任务而无需特定训练的基础模型已经在视觉和语言应用中引发了机器学习的革命。然而&#xff0c;涉及图结构数据的应用仍然是基础模型面临的一个难题&#xff0c;因为每个图都有独特的特征和标签空间。传统的图机器学习模型&#xff0c;如图神经网络&…...

动态规划.

目录 &#xff08;一&#xff09;递归到动规的一般转化方法 &#xff08;二&#xff09;动规解题的一般思路 1. 将原问题分解为子问题 2. 确定状态 3. 确定一些初始状态&#xff08;边界状态&#xff09;的值 4. 确定状态转移方程 &#xff08;三&#xff09;能用动规解…...

PHP常用函数

字符串 strlen()获取字符串长度strpos&#xff08;&#xff09;在字符串内查找一个字符或一段指定的文本&#xff0c;返回第一次出现的位置或falsestripos&#xff08;&#xff09;同上&#xff0c;但不区分大小写strrpos&#xff08;&#xff09;同上上&#xff0c;返回最后一…...

完全用python 实现消息中间件4

为了进一步完善这个消息中间件&#xff0c;我们可以添加以下功能&#xff1a; 消息确认&#xff1a;客户端可以发送一个确认消息&#xff0c;表明消息已经被正确接收。消息队列&#xff1a;使用一个队列来存储消息&#xff0c;而不是直接存储在字典中。多消费者支持&#xff1…...

公司新来的两个Java后端,因题背太熟轻松过面试?

以前面试是背八股文&#xff0c;而2024年的后端面试都是流行问场景题&#xff01;建议大家把面试想简单一点&#xff0c;顺的场景题直接给有需要的人&#xff0c;希望能对大家有所帮助&#xff01; 由于平台篇幅原因&#xff0c;很多java面试资料内容展示不了&#xff0c;需要…...

Pinia状态管理库

为了跨组件传递JWT令牌&#xff0c;我们就会利用Pinia状态管理库&#xff0c;它允许跨组件或页面共享状态。 使用Pinia步骤&#xff1a; 安装pinia&#xff1a;cnpm install pinia 在vue应用实例中使用pinia 在src/stores/token.js中定义store 在组件中使用store 1.在main.js文…...

利用ffmpeg转码视频为gif图片,调整gif图片的大小

【1】压缩gif图片大小 一般发布技术文章的时候经常要插入GIF图演示软件效果&#xff0c;但是一些编辑器总是限制大小&#xff0c;但是录制的时候可能一不小心就搞大了。 要将 GIF 图片大小限制在 10MB 内&#xff0c;可以使用 FFmpeg 进行压缩。 以下是一个ffmpeg的命令&…...

【Java 第四篇章】流程控制、容器

一、流程控制 1、概念 //1.if//2.if...else//3.if...else if...else...//4.switch//5.跳出循环体&#xff1a;break和continue2、语法 //1. ifif(条件表达式){//执行代码块}//2.if...elseif(条件表达式){//条件表达式为真执行的代码块} else {//条件表达式为假执行的代码块}//…...

华为云全域Serverless技术创新:全球首创通用Serverless平台被ACM SIGCOMM录用

华为开发者大会2024&#xff08;HDC 2024&#xff09;在东莞松山湖圆满结束&#xff0c;期间华为云主办的“全域Serverless时代&#xff1a;技术创新引领&#xff0c;赋能行业实践”专题论坛&#xff0c;向广大开发者传递了Serverless领域的前沿思考和实践&#xff0c;现场座无…...

除自身以外数组的相乘 C++

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂…...

Element UI 如何配置文件来设置全局的语言选项。

Element UI 允许你通过配置文件来设置全局的语言选项&#xff0c;这样你可以方便地切换组件的语言。以下是如何配置 Element UI 以设置全局语言选项的步骤&#xff1a; 1. 安装 Element UI 确保你已经安装了 Element UI。 npm install element-ui --save2. 引入语言包 Elem…...

Windows 常用命令集锦

目录 一、文件和目录管理 1.1 文件操作 1.2 目录操作 二、系统信息 2.1 基本系统信息 2.2 硬件信息 三、网络管理 3.1 基本网络命令 3.2 网络诊断 四、进程管理 4.1 查看进程 4.2 管理进程 五、磁盘管理 5.1 磁盘操作 5.2 磁盘分区 六、IIS操作 通过上述命令&am…...

第一阶段面试问题(后半部分)

1. c语言中const *p的用法 &#xff08;1&#xff09;const int *p; 或 int const *p; 指向常量整数的指针&#xff0c;通过这个指针不能修改它所指向的整数值&#xff0c;但可以修改指针本身来指向其他地址 const int a 10; const int *p &a; // *p 20; // 错误&…...

【AIGC】ComfyUI入门-使用ComfyUI_MagicClothing插件在生成图片时候出现的问题

最近想自己实现自动换装的工作流,在使用ComfyUI_MagicClothing插件的时候,出现了一个奇怪的问题。这个问题不是插件的问题,是环境配置问题。 问题内容如下: Exception during processing!!! D:\a_work\1\s\onnxruntime\python\onnxruntime_pybind_state.cc:891 onnxrunti…...

巴黎奥运会8K转播科技为国产品牌自主研发设计

这个夏天&#xff0c;顶流是属于巴黎奥运会中国队的。 20枚金牌、15枚银牌、12枚铜牌......这个数字正随着赛事推进而不停在增加。赛场之上&#xff0c;中国健儿奋力拼搏、捷报频传&#xff0c;令人热血沸腾&#xff1b;赛场之外&#xff0c;另一支来自中国企业的“奥运选手”…...

【Material-UI】Button 组件中的图标和标签按钮(Buttons with Icons and Label)详解

文章目录 一、基础用法1. 左侧图标&#xff08;startIcon&#xff09;2. 右侧图标&#xff08;endIcon&#xff09; 二、图标与标签的搭配三、高级用法和最佳实践1. 自定义图标2. 视觉一致性3. 动态图标 四、总结 在现代用户界面设计中&#xff0c;图标在提高用户体验&#xff…...

K个一组翻转链表(LeetCode)

题目 给你链表的头节点 &#xff0c;每 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值&…...

2-56 基于matlab的图像融合增强技术

基于matlab的图像融合增强技术。通过原始图像——傅里叶变换——频率域滤波处理——傅里叶变换——增强后的图像。傅立叶变换以及傅立叶反变换.过程就是将空间的信息分解为在频率上的表示,通过傅立叶正反变换的处理,才使得频率域上的处理可以用于图像的增强。程序已调通&#x…...