JVM的内存结构详解「重点篇」

news2024/11/18 3:34:11

一、JVM虚拟机数据区

· 虚拟机栈

        1、  线程私有

        2、 每个方法被执行的时候都会创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用的过程就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。

        3、栈帧: 是用来存储数据和部分过程结果的数据结构

        4、 栈帧大小确定时间: 编译期确定,不受运行期数据影响

        5、虚拟机栈的生命周期和线程是相同

        6、虚拟机栈是一个后入先出的栈。栈帧是保存在虚拟机栈中的,栈帧是用来存储数据和存储部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)

        7、线程运行过程中,只有一个栈帧是处于活跃状态,称为“当前活跃栈帧”,当前活动栈帧始终是虚拟机栈的栈顶元素:如图->

        8、栈帧细节如图:

 

        9、局部变量表是一组局部变量值存储空间,用于存放方法参数和方法内部定义的局部变量。在Java文件编译为Class文件时,就在方法表的Code属性的max_locals数据项中确定了该方法需要分配的最大局部变量表的容量 

        10、操作数栈也常被称为操作栈,它是一个后入先出栈。JVM底层字节码指令集是基于栈类型的,所有的操作码都是对操作数栈上的数据进行操作,对于每一个方法的调用,JVM会建立一个操作数栈,以供计算使用。和局部变量一样。操作数栈的最大深度也是编译的时候写入到方法表的code属性的max_stacks数据项中。操作数栈的每一个元素可以是任意的Java数据类型,包括long、double。32位数据类型所占的栈容量为1,64位数据类型所占的栈容量为2。栈容量的单位为“字宽”,对于32位虚拟机来说,一个“字宽”占4个字节,64位虚拟机来说,一个“字宽”占8个字节。当一个方法刚刚执行的时候,这个方法的操作数栈是空的,在方法执行的过程中,会有各种字节码指向操作数栈中写入和提取值,也就是入栈与出栈操作

        11、每个栈帧都包含一个指向运行时常量池中该栈帧所属性方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。在Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。这些符号引用一部分会在类加载阶段或第一次使用的时候转化为直接引用,这种转化称为静态解析。另外一部分将在每一次的运行期期间转化为直接引用,这部分称为动态连接

        12、当一个方法被执行后,有两种方式退出这个方法。第一种方式是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调用当前方法的的方法称为调用者),是否有返回值和返回值的类型将根据遇到何种方法返回指令来决定,这种退出方法方式称为正常完成出口(Normal Method Invocation Completion)。另外一种退出方式是,在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,无论是Java虚拟机内部产生的异常,还是代码中使用athrow字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方式称为异常完成出口(Abrupt Method Invocation Completion)。一个方法使用异常完成出口的方式退出,是不会给它的调用都产生任何返回值的。     无论采用何种方式退出,在方法退出之前,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态。一般来说,方法正常退出时,调用者PC计数器的值就可以作为返回地址,栈帧中很可能会保存这个计数器值。而方法异常退出时,返回地址是要通过异常处理器来确定的,栈帧中一般不会保存这部分信息。 方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用都栈帧的操作数栈中,调用PC计数器的值以指向方法调用指令后面的一条指令等

· 本地方法栈

        1、本地方法本质上时依赖于实现的,虚拟机实现的设计者们可以自由地决定使用怎样的机制来让Java程序调用本地方法

        2、任何本地方法接口都会使用某种本地方法栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法

        3、很可能本地方法接口需要回调Java虚拟机中的Java方法,在这种情况下,该线程会保存本地方法栈的状态并进入到另一个Java栈

        4、如下图展示了JAVA虚拟机内部线程运行的全景图。一个线程可能在整个生命周期中都执行Java方法,操作它的Java栈;或者它可能毫无障碍地在Java栈和本地方法栈之间跳转

·  堆(划重点)

        1、堆的内存结构如图:

        2、堆内存分为年轻代(Young Generation)、老年代(Old Generation)

        3、年轻代又分为Eden和Survivor区。Survivor区由FromSpace和ToSpace组成。Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1

        4、堆内存用途:存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收

        5、JDK1.8版本废弃了永久代,替代的是元空间(MetaSpace),元空间与永久代上类似,都是方法区的实现,他们最大区别是:元空间并不在JVM中,而是使用本地内存

        6、元空间有注意有两个参数:

MetaspaceSize :初始化元空间大小,控制发生GC阈值

MaxMetaspaceSize : 限制元空间大小上限,防止异常占用过多物理内存

        7、移除永久代原因:为融合HotSpot JVM与JRockit VM(新JVM技术)而做出的改变,因为JRockit没有永久代。

有了元空间就不再会出现永久代OOM问题了

        8、各代关系:

新生成的对象首先放到年轻代Eden区,当Eden空间满了,触发Minor GC,存活下来的对象移动到Survivor0区,Survivor0区满后触发执行Minor GC,Survivor0区存活对象移动到Suvivor1区,这样保证了一段时间内总有一个survivor区为空。经过多次Minor GC仍然存活的对象移动到老年代。

老年代存储长期存活的对象,占满时会触发Major GC=Full GC,GC期间会停止所有线程等待GC完成,所以对响应要求高的应用尽量减少发生Major GC,避免响应超时。

Minor GC : 清理年轻代

Major GC : 清理老年代

Full GC : 清理整个堆空间,包括年轻代和永久代

所有GC都会停止应用所有线程

        9、QA

为什么survivor分为两块相等大小的幸存空间?

主要为了解决碎片化。如果内存碎片化严重,也就是两个对象占用不连续的内存,已有的连续内存不够新对象存放,就会触发GC

为什么会堆内存溢出?

在年轻代中经过GC后还存活的对象会被复制到老年代中。当老年代空间不足时,JVM会对老年代进行完全的垃圾回收(Full GC)。如果GC后,还是无法存放从Survivor区复制过来的对象,就会出现OOM(Out of Memory)

OOM常见原因分析

老年代内存不足:java.lang.OutOfMemoryError:Javaheapspace

解决办法:java 堆内存溢出, 此种情况最常见, 一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露, 需要通过内存监控软件查找程序中的泄露代码, 而堆大小可以通过虚拟机参数 - Xms,-Xmx 等修改

永久代内存不足:java.lang.OutOfMemoryError:PermGenspac

解决办法:java 永久代溢出, 即方法区溢出了, 一般出现于大量 Class 或者 jsp 页面, 或者采用 cglib 等反射机制的情况, 因为上述情况会产生大量的 Class 信息存储于方法区。当出现此种情况时可以通过更改方法区的大小来解决, 使用类似 - XX:PermSize=64m -XX:MaxPermSize=256m 的形式修改。注意, 过多的常量尤其是字符串也会导致方法区溢出

java.lang.StackOverflowError
   解决方法: JAVA 虚拟机栈溢出, 一般是由于程序中存在死循环或者深度递归调用造成的, 栈大小设置太小也会出现此种溢出。可以通过虚拟机参数 - Xss 来设置栈的大小

重点来了
(1)、Java heap space报错的原因及如何解救:

        (1.1)、请求创建一个超大对象,通常是一个大数组,举例子:从文件或者db中读取了100w条数据,申明了一个List或者Map,一条数据的大小哪怕1kb大小,这100w数据就要占用1Gb内存

        这里给个样例代码,后面不会再上复现代码了,各位自己下去动手去验证:

package com.feixiang.platform.stu.jvm.oom.stack;

import com.feixiang.platform.stu.jvm.reference.strong.User;

import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description: 创造一个OOM来实验:
 * 一定要够大的数组对象
 * 运行参数一定要修改,不然无法如愿
 *
 * @PackageName com.feixiang.platform.stu.jvm.oom.stack
 * @Author: ldwtxwhspring
 * @Date: 2023-12-02 下午6:01
 * @Version: 1.0.0
 */
public class StackHeapOomExample {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        for(int i=0;i<1000000;i++){
            User user = new User();
            user.setId(i);
            user.setName("feixiang_"+i);
            user.setAddress("xxxx省—xxx市-xxx路-xxx小区-xxx楼"+i+"号房间");
            user.setMobile("133xxxx5680");
            userList.add(user);
        }
    }
}

运行参数修改如图:

 

运行结果如图:

 

        (1.2)、超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值。例如:双十一几万件商品快速被推向订单池,连续操作有不断锁库存加事务完整性逻辑,这些内存肯定不会被回收,而且会存在于完整的订单周期内。

        (1.3)、过度使用(Finalizer),该对象没有立即被 GC

        (1.4)、内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收,例如:读写文件完成没有刷新流或者没有关闭管道。

解决方法:

        针对大部分情况,通常只需要通过 -Xmx 参数调高 JVM 堆内存空间即可。如果仍然没有解决,可以参考以下情况做进一步处理:

        

  • 如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。
  • 如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级。
  • 如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接。
  • 对于外部网络请求,可以设置超时时间,请求回调改造
(2)、PermGen space报错原因分析及解救:

       (2.1)、 该错误表示永久代 (Permanent Generation) 已用满, 通常是因为加载的 class 数目太多或体积太大

        (2.2)、原因分析,永久代存储对象主要包括以下几类:        

  • 加载/缓存到内存中的 class 定义,包括类的名称,字段,方法和字节码;
  • 常量池;
  • 对象数组/类型数组所关联的 class;
  • JIT 编译器优化后的 class 信息。
  • PermGen 的使用量与加载到内存的 class 的数量/大小正相关。

      (2.2)、解决方案,根据 Permgen space 报错的时机,可以采用不同的解决方案,如下所示:

  • 程序启动报错,修改 -XX:MaxPermSize 启动参数,调大永久代空间。
  • 应用重新部署时报错,很可能是没有应用没有重启,导致加载了多份 class 信息,只需重启 JVM 即可解决。
  • 运行时报错,应用程序可能会动态创建大量 class,而这些 class 的生命周期很短暂,但是 JVM 默认不会卸载 class,可以设置 -XX:+CMSClassUnloadingEnabled 和 -XX:+UseConcMarkSweepGC这两个参数允许 JVM 卸载 class。
  • 如果上述方法无法解决,可以通过 jmap 命令 dump 内存对象 jmap-dump:format=b,file=dump.hprof ,然后利用 Eclipse MAT Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation 功能逐一分析开销最大的 classloader 和重复 class
(3)、java.lang.OutOfMemoryError:GC overhead limit exceeded 错误原因及解决:

当 Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次,就会抛出 java.lang.OutOfMemoryError:GC overhead limit exceeded 错误。简单地说,就是应用程序已经基本耗尽了所有可用内存, GC 也无法回收。

此类问题的原因与解决方案跟 Javaheap space 非常类似,请回看上文

(4)、Metaspace错误原因及解救:

JDK 1.8 使用 Metaspace 替换了永久代(Permanent Generation),该错误表示 Metaspace 已被用满,通常是因为加载的 class 数目太多或体积太大。

此类问题的原因与解决方法跟 Permgenspace 非常类似,可以参考上文。需要特别注意的是调整 Metaspace 空间大小的启动参数为 -XX:MaxMetaspaceSize。

(5)、Unable to create new native thread错误原因及解救:

        (5.1)、每个 Java 线程都需要占用一定的内存空间,当 JVM 向底层操作系统请求创建一个新的 native 线程时,如果没有足够的资源分配就会报此类错误。

        (5.2)、原因分析,JVM 向 OS 请求创建 native 线程失败,就会抛出 Unableto createnewnativethread,常见的原因包括以下几类:

  • 线程数超过操作系统最大线程数 ulimit 限制;
  • 线程数超过 kernel.pid_max(只能重启);
  • native 内存不足;

        (5.3)、该问题发生的常见过程主要包括以下几步:

  • JVM 内部的应用程序请求创建一个新的 Java 线程;
  • JVM native 方法代理了该次请求,并向操作系统请求创建一个 native 线程;
  • 操作系统尝试创建一个新的 native 线程,并为其分配内存;
  • 如果操作系统的虚拟内存已耗尽,或是受到 32 位进程的地址空间限制,操作系统就会拒绝本次 native 内存分配;
  • JVM 将抛出 java.lang.OutOfMemoryError:Unableto createnewnativethread 错误。

        (5.4)、解决方案

  • 升级配置,为机器提供更多的内存;
  • 降低 Java Heap Space 大小;
  • 修复应用程序的线程泄漏问题;
  • 限制线程池大小;
  • 使用 -Xss 参数减少线程栈的大小;
  • 调高 OS 层面的线程最大数:执行 ulimia-a 查看最大线程数限制,使用 ulimit-u xxx 调整最大线程数限制ulimit -a … 省略部分内容 … max user processes (-u) 16384
(6)、Out of swap space原因分析及解救:

        (6.1)、该错误表示所有可用的虚拟内存已被耗尽。虚拟内存(Virtual Memory)由物理内存(Physical Memory)和交换空间(Swap Space)两部分组成。当运行时程序请求的虚拟内存溢出时就会报 Outof swap space? 错误。

        (6.2)、原因分析,该错误出现的常见原因包括以下几类:

  • 地址空间不足;
  • 物理内存已耗光;
  • 应用程序的本地内存泄漏(native leak),例如不断申请本地内存,却不释放。
  • 执行 jmap-histo:live 命令,强制执行 Full GC;如果几次执行后内存明显下降,则基本确认为 Direct ByteBuffer 问题。

        (6.3)、解决方案,根据错误原因可以采取如下解决方案:

  • 升级地址空间为 64 bit;
  • 使用 Arthas 检查是否为 Inflater/Deflater 解压缩问题,如果是,则显式调用 end 方法。
  • Direct ByteBuffer 问题可以通过启动参数 -XX:MaxDirectMemorySize 调低阈值。
  • 升级服务器配置/隔离部署,避免争用。
(7)、Kill process or sacrifice child分析及解决:

        (7.1)、有一种内核作业(Kernel Job)名为 Out of Memory Killer,它会在可用内存极低的情况下“杀死”(kill)某些进程。OOM Killer 会对所有进程进行打分,然后将评分较低的进程“杀死”,具体的评分规则可以参考 Surviving the Linux OOM Killer。不同于其他的 OOM 错误, Killprocessorsacrifice child 错误不是由 JVM 层面触发的,而是由操作系统层面触发的。

        (7.2)、原因分析

默认情况下,Linux 内核允许进程申请的内存总量大于系统可用内存,通过这种“错峰复用”的方式可以更有效的利用系统资源。

然而,这种方式也会无可避免地带来一定的“超卖”风险。例如某些进程持续占用系统内存,然后导致其他进程没有可用内存。此时,系统将自动激活 OOM Killer,寻找评分低的进程,并将其“杀死”,释放内存资源。

        (7.3)、解决方案

  • 升级服务器配置/隔离部署,避免争用。
  • OOM Killer 调优。
(8)、Direct buffer memory原因及解救:

        (8.1)、java 允许应用程序通过 Direct ByteBuffer 直接访问堆外内存,许多高性能程序通过 Direct ByteBuffer 结合内存映射文件(Memory Mapped File)实现高速 IO。

        (8.2)、原因分析

  • Direct ByteBuffer 的默认大小为 64 MB,一旦使用超出限制,就会抛出 Directbuffer memory 错误。

        (8.3)、解决方案

  • Java 只能通过 ByteBuffer.allocateDirect 方法使用 Direct ByteBuffer,因此,可以通过 Arthas 等在线诊断工具拦截该方法进行排查。
  • 检查是否直接或间接使用了 NIO,如 netty,jetty 等。
  • 通过启动参数 -XX:MaxDirectMemorySize 调整 Direct ByteBuffer 的上限值。
  • 检查 JVM 参数是否有 -XX:+DisableExplicitGC 选项,如果有就去掉,因为该参数会使 System.gc() 失效。
  • 检查堆外内存使用代码,确认是否存在内存泄漏;或者通过反射调用 sun.misc.Cleaner 的 clean() 方法来主动释放被 Direct ByteBuffer 持有的内存空间。
  • 内存容量确实不足,升级配置。
· 程序计数器

        1、线程私有

        2、每个线程一块内存,指向当前正在执行的字节码的行号。如果当前线程是native方法,则其值为null

        3、如果执行的是java方法,那么记录的是正在执行的虚拟机字节码指令的地址的地址,如果是native方法,计数器的值为空(undefined)

        4、这块内存区域是虚拟机规范中唯一没有OutOfMemoryError的区域

二、本地内存

· 元数据区

1、主要用来保存被虚拟机加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据

2、存在OOM的区:一个元数据区的大小决定了Java虚拟机可以装载的类的多少

3、包括final修饰的变量、字面量、类和接口全限定名、字段、方法名称以及修饰符等永恒不变的东西

4、并不是所有的字面量都会存储在类文件常量池中,比如对于方法内(注意是方法)整数字面量,如果值在-32768~32767之间则会被直接嵌入JVM指令中去,不会保存在常量池中

· 直接内存

1、java通过native方法去调用

2、在调用这种native方法的时候,就会有线程对应的本地方法栈,这个其实类似于java虚拟机栈。也是存放各种native方法的局部变量表之类的信息

3、还有一块区域,不是jvm的,通过NIO中的allocateDirect这种API,可以在jvm堆外分配内存空间,然后通过java虚拟机栈里的DirectByteBuffer来引用和操作堆外内存空间

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

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

相关文章

数字化升级,智慧医疗新时代——医院陪诊服务的技术创新

在信息技术飞速发展的今天&#xff0c;医疗服务正迎来数字化升级的新时代。本文将探讨如何通过先进技术的应用&#xff0c;为医院陪诊服务注入更多智慧元素&#xff0c;提升患者和家属的医疗体验。 1. 创新医疗预约系统 # Python代码演示医疗预约系统的简单实现 class Medic…

最新国内可用GPT4,Midjourney绘画网站+使用教程

一、前言 ChatGPT GPT4.0&#xff0c;Midjourney绘画&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和用户进行创作交流。 然而&#xff0c;GPT-4对普…

ChatGPT有什么新奇的使用方式?

2023&#xff0c;ChatGPT几乎席卷了所有行业&#xff0c;并且具有不可测量的巨大潜力等着我们去挖掘。 越来越多人对ChatGPT的应用产生兴趣&#xff0c;知乎上“ChatGPT有什么新奇的使用方式&#xff1f;”这一个热门话题的兴起就是最好的证明。 写作&#xff0c;毫无疑问&…

【Java探索之旅】我与Java的初相识(一):Java的特性与优点及其发展史

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java入门到精通 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 一. Java语言概述与优势1.1 Java的概述1.2 Java语言的优势 二. Java领域与发展史2.1 Java的使用领域2.…

中国开源大模型登顶HuggingFace排行榜

12月8日消息&#xff0c;全球最大的开源大模型社区HuggingFace日前公布了最新的开源大模型排行榜&#xff0c;阿里云通义千问力压Llama2等国内外开源大模型登顶榜首。 HuggingFace的开源大模型排行榜&#xff08;Open LLM Leaderboard&#xff09;是目前大模型领域最具权威性的…

基于python+unittest实现接口自动化测试

简介 本文通过从Postman获取基本的接口测试Code简单的接口测试入手&#xff0c;一步步调整优化接口调用&#xff0c;以及增加基本的结果判断&#xff0c;讲解Python自带的Unittest框架调用&#xff0c;期望各位可以通过本文对接口自动化测试有一个大致的了解。 为什么要做接口…

VMware虚拟机搭建+云平台购买搭建(阿里云+UCloud)【设置主机名以及主机名映射、配置免密登录、配置JDK】

本地虚拟机的搭建 一、准备网段 在VMware的虚拟网络编辑器中将VMnet8虚拟网卡的 网段设置为&#xff1a;192.168.88.0网关设置为&#xff1a;192.168.88.2 二、下载CentOS操作系统文件&#xff0c;并安装 三、克隆多台虚拟机 依照同样的方法&#xff0c;克隆出node2…

火狐,要完了!

在过去几年中&#xff0c;关于Firefox 浏览器的衰落有过不少讨论。目前来说&#xff0c;很多公共的以及私营的大型网站都缺乏对Firefox的适当支持。但是Firefox也多次试图“自救”&#xff0c;甚至就在不久前&#xff0c;Mozilla 通过官博发文&#xff0c;表示 Firefox 在 2023…

AWS KeyPair密钥格式转换PPK<>PEM

概述说明 PEM&#xff08;Privacy Enhanced Mail&#xff09;和PPK&#xff08;Putty Private Key&#xff09;都是与加密和安全相关的文件格式&#xff0c;通常用于存储私钥信息。它们在不同的上下文中使用&#xff0c;并且与不同的软件和协议相关联。 PEM&#xff08;Priva…

基于SpringBoot的学生管理系统

基于SpringBoot的学生管理系统 文章目录 基于SpringBoot的学生管理系统 一.引言二.系统设计三.技术架构四.功能实现五.界面展示六.源码获取 一.引言 学生管理系统是一种用于管理学生信息、课程安排、成绩记录等学生相关数据的软件系统。它通过集中管理学生信息&#xff0c;提供…

Java Web应用小案例 - 实现用户登录功能

文章目录 一、使用纯JSP方式实现用户登录功能&#xff08;一&#xff09;项目概述&#xff08;二&#xff09;实现步骤1、创建Web项目2、创建登录页面 二、使用JSPServlet方式实现用户登录功能三、使用JSPServletDB方式实现用户登录功能 一、使用纯JSP方式实现用户登录功能 &a…

spring 的概述和入门

​ 我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; …

ffmpeg格式转换 免费使用视频格式转换教程

下载安装 首先去官网下载ffmpeg的软件包https://ffmpeg.org/ 如果是windows可以在直接下载编译好的软件包 https://www.gyan.dev/ffmpeg/builds/ 进入解压后的目录&#xff0c;子目录bin中的ffmpeg.exe就是我们要使用的转换器 视频信息查看 打开cmd控制台&#xff0c;从…

Linux嵌入式配置USB鼠标支持+触摸板

在linux嵌入式中加入鼠标支持&#xff0c;首先在内核里面将mice驱动加入编译&#xff0c;这里用到的是usb所以还要有usb的支持&#xff0c;下载到板子上启动 1、定位鼠标 要用鼠标&#xff0c;首先要知道生成的鼠标设备是哪个&#xff0c;直接直接ls input目录&#xff0c;当…

HalconDotNe.HOperatorException:“HALCON error#1401:

Wrong number of values of control parameter 1in operator draw_rectangle2_mod错误提示参数值不对&#xff0c;是窗体hv_WindowHandle错了&#xff0c;窗体未创建。

【Linux系统编程】项目自动化构建工具make/Makefile

介绍&#xff1a; make和Makefile是用于编译和构建C/C程序的工具和文件。Makefile是一个文本文件&#xff0c;其中包含了编译和构建程序所需的规则和指令。它告诉make工具如何根据源代码文件生成可执行文件&#xff0c;里面保存的是依赖关系和依赖方法。make是一个命令行工具&a…

[ 蓝桥杯Web真题 ]-Markdown 文档解析

目录 介绍 准备 目标 规定 思路 补充知识 解法参考 介绍 Markdown 因为其简洁的语法大受欢迎&#xff0c;已经成为大家写博客或文档时必备的技能点&#xff0c;众多博客平台都提倡用户使用 Markdown 语法进行文章书写&#xff0c;然后再发布后&#xff0c;实时的将其转化…

如何入驻抖音本地生活服务商,门槛太高怎么办?

随着抖音本地生活服务市场的逐渐成熟&#xff0c;越来越多平台开始涉及本地生活服务领域&#xff0c;而本地生活服务商成了一个香窝窝&#xff0c;为了保护用户权益和平台生态&#xff0c;对入驻入驻抖音本地生活服务商的条件及审核也越来越严格&#xff0c;这让很多想成为抖音…

【Flink系列四】Window及Watermark

3.1、window 在 Flink 中 Window 可以将无限流切分成有限流&#xff0c;是处理有限流的核心组件&#xff0c;现在 Flink 中 Window 可以是时间驱动的&#xff08;Time Window&#xff09;&#xff0c;也可以是数据驱动的&#xff08;Count Window&#xff09;。 Flink中的窗口…

CSS特效025:旋转的loading状态

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花边是描述了一些CSS…