【JVM详解一】类加载过程与内存区域划分
一、简介
1.1 概述
JVM是Java Virtual Machine(Java虚拟机)的缩写,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相关的信息,使得Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可在多种平台上不加修改的运行,这也是Java能够“一次编译,到处运行的”原因。
所谓java能实现跨平台,是由在不同平台上运行不同的虚拟机决定的,因此java文件的执行不直接在操作系统上执行,而是通过jvm虚拟机执行,我们可以从这张图看到,JVM并没有直接与硬件打交道,而是与操作系统交互用以执行java程序。
1.2 JRE、JDK和JVM的关系
JRE(Java Runtime Environment, Java运行环境)是Java平台,所有的程序都要在JRE下才能够运行。包括JVM和Java核心类库和支持文件。
JDK(Java Development Kit,Java开发工具包)是用来编译、调试Java程序的开发工具包。包括Java工具(javac/java/jdb等)和Java基础的类库(java API )。
JVM(Java Virtual Machine, Java虚拟机)是JRE的一部分。JVM主要工作是解释自己的指令集(即字节码)并映射到本地的CPU指令集和OS的系统调用。Java语言是跨平台运行的,不同的操作系统会有不同的JVM映射规则,使之与操作系统无关,完成跨平台性。
使用JDK(调用JAVA API)开发JAVA程序后,通过JDK中的编译程序(javac)将Java程序编译为Java字节码,在JRE上运行这些字节码,JVM会解析并映射到真实操作系统的CPU指令集和OS的系统调用。
二、JVM架构
JVM的架构分为多个子系统,主要包括类加载子系统、运行时数据区、垃圾回收机制和执行引擎等。
2.1 类加载子系统
JVM 将 class 字节码文件加载到内存中, 并将这些静态数据转换成方法区中的运行时数据结构,在堆(并不一定在堆中,HotSpot在方法区中)中生成一个代表这个类的 java.lang.Class 对象,作为方法区类数据的访问入口。
2.1.1 类加载器
把类加载阶段的 “ 通过一个类的全限定名来获取描述此类的二进制字节流 ” 这个动作交给虚拟机之外的类加载器来完成。这样的好处在于,我们可以自行实现类加载器来加载其他格式的类,只要是二进制字节流就行,这就大大增强了加载器灵活性。系统自带的类加载器分为三种:
- 启动类加载器 ===》 Bootstrap ClassLoader
- 扩展类加载器 ===》 Extension ClassLoader
- 应用程序类加载器 ===》Application ClassLoader
2.1.1.1 双亲委派机制
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父加载器去完成,每个层次的类加载器都是如此。因此所有的加载请求最终都会传送到Bootstrap类加载器(启动类加载器)中,只有父类加载反馈自己无法加载这个请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
层级结构如下图所示:
双亲委派模型的优点:
java类随着它的加载器一起具备了一种带有优先级的层次关系。
例如类 java.lang.Object ,它存放在 rt.jar 之中,无论哪一个类加载器都要加载这个类,最终都是双亲委派模型最顶端的 Bootstrap 类加载器去加载。因此 Object 类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户编写了一个称为 “java.lang.Object” 的类,并存放在程序的ClassPath中,那系统中将会出现多个不同的 Object 类,java 类型体系中最基础的行为也就无法保证,应用程序也将会一片混乱。
2.1.1.2 自定义类加载器
继承 ClassLoader 类,重写 findClass() 方法:
2.1.2 类加载过程
类的加载过程如下:
JVM类加载机制分为五个部分:加载,校验,准备,解析,初始化,下面我们就分别来看一下这五个过程。其中加载、校验、准备、初始化和卸载这个五个阶段的顺序是固定的,而解析则未必。为了支持动态绑定,解析这个过程可以发生在初始化阶段之后。
加载(Loading):类加载器从字节流中读取类的二进制数据并将其加载到内存中。
验证(Verification):验证类的字节码是否符合JVM规范,防止恶意代码的侵入。
准备(Preparation):为类的静态变量分配内存并设置默认值。
解析(Resolution):将类中的符号引用解析为直接引用。
初始化(Initialization):执行类的构造方法,初始化类的静态变量和静态代码块。
2.1.2.1 加载
类加载器从字节流中读取类的二进制数据并将其加载到内存中。
加载过程主要完成三件事情:
- 通过类的全限定名来获取定义此类的二进制字节流
- 将这个类字节流代表的静态存储结构转为方法区的运行时数据结构
- 在堆中生成一个代表此类的 java.lang.Class 对象,作为访问方法区这些数据结构的入口。
这个过程主要由类加载器完成。
2.1.2.2 校验
验证类的字节码是否符合JVM规范,防止恶意代码的侵入。
- 文件格式验证:基于字节流验证。
- 是否以魔数0xCAFEBABE开头。
- 主、次版本号是否在当前虚拟机处理范围之内。
- 常量池的常量中是否有不被支持的常量类型(检查常量tag标志)。
- 指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量。
- CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据。
- Class文件中各个部分及文件本身是否有被删除的或附加的其他信息。
- 元数据验证:基于方法区的存储结构验证。
- 这个类是否有父类(除了java.lang.Object之外,所有类都应当有父类)。
- 这个类是否继承了不允许被继承的类(被final修饰的类)。
- 如果这个类不是抽象类,是否实现了其父类或接口之中所要求实现的所有方法。
- 类中的字段、方法是否与父类产生矛盾(例如覆盖了父类的final字段,或者出现不符合规则的方法重载,例如方法参数都一致,但返回值类型却不同等等)。
- 字节码验证:基于方法区的存储结构验证。主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
- 保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,例如不会出现类似这样的情况:在操作数栈放置了一个int类型的数据,使用时却按long类型来加载入本地变量表中。
- 保证跳转指令不会跳转到方法体以外的字节码指令上。
- 保证方法体中的类型转换是有效的,例如可以把一个子类对象赋值给父类数据类型,但是把父类对象赋值给子类数据类型,甚至把对象赋值给与它毫无继承关系、完全不相干的一个数据类型,则是危险不合法的。
- 符号引用验证:基于方法区的存储结构验证。可以看作是类对自身以外(常量池中的各种符号引用)的信息进行匹配性校验。
- 符号引用中通过字符串描述的全限定名是否能够找到对应的类。
- 在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段。
- 符号引用中的类、字段、方法的访问性(private、protected、public、default)是否可被当前类访问。
2.1.2.3 准备
为类变量分配内存(不包括实例变量),并将其初始化为默认值。(此时为默认值,在初始化的时候才会给变量赋值)即在方法区中分配这些变量所使用的内存空间。例如:
此时在准备阶段过后的初始值为0而不是123;将value赋值为123的 putstatic 指令是程序被编译后,存放于类构造器<clinit>方法之中。
特例:
此时value的值在准备阶段过后就是123。
2.1.2.4 解析
把类型中的符号引用转换为直接引用。
- 符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。
- 直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在
主要有以下四种:
- 类或接口的解析
- 字段解析
- 类方法解析
- 接口方法解析
2.1.2.5 初始化
初始化阶段是执行类构造器<clinit>方法的过程。<clinit>方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证<clinit>方法执行之前,父类的<clinit>方法已经执行完毕。如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成<clinit>方法。
java中,对于初始化阶段,有且只有以下五种情况才会对要求类立刻“初始化”(加载,验证,准备,自然需要在此之前开始):
- 使用 new 关键字实例化对象、访问或者设置一个类的静态字段(被final修饰、编译器优化时已经放入常量池的例外)、调用类方法,都会初始化该静态字段或者静态方法所在的类。
- 初始化类的时候,如果其父类没有被初始化过,则要先触发其父类初始化。
- 使用 java.lang.reflect 包的方法进行反射调用的时候,如果类没有被初始化,则要先初始化。
- 虚拟机启动时,用户会先初始化要执行的主类(含有main)。
- jdk 1.7后,如果 java.lang.invoke.MethodHandle 的实例最后对应的解析结果是 REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄,并且这个方法所在类没有初始化,则先初始化。
2.2 运行时数据区(HotSpot虚拟机)
JVM在程序执行时,管理着多个内存区域,称为运行时数据区。每个区域有不同的用途,主要包括以下几个区域:
- 方法区:存储类的相关信息(类信息、常量、静态变量、方法数据等)。
- 堆(Heap):存储Java对象,是垃圾回收器管理的区域。
- 虚拟机栈(JVM Stack):每个线程都有一个栈,用来存储方法的局部变量、操作数栈、返回地址等信息。
- 程序计数器(PC Register):存储当前线程正在执行的字节码的地址。
- 本地方法栈(Native Method Stack):为JVM调用本地方法(如C/C++编写的库)提供支持。
2.2.1 程序计数器
线程私有;是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器,唯一不会造成 OutOfMemoryError 情况的区域。不过当线程执行的是 Native 方法的时候这个计数器中的值为 undefined 。
2.2.2 java虚拟机栈
线程私有;描述的是 java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。栈帧指执行一个方法所使用的那部分栈,线程的所有方法的栈帧串起来就组成了一个完整的 java 虚拟机栈。java 虚拟机栈针对线程而言,线程里的方法对应栈中的元素----栈帧;每执行一个方法,就为这个方法创建对应的栈帧,并 push 到 线程这个大容器-----java虚拟机栈 中,执行完成就 pop 出栈。
局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、long、float、double)、对象引用(用来指向内存中分配的类实例或者数组) 和 returnAddress 类型(指向字节码的指针)。注:long和double会占用2个局部变量空间(8字节),其余数据类型只占用一个(4字节)。对于局部变量,如果是基本类型,会把值直接存储在栈;如果是引用类型,比如String s = new String("william");会把其对象存储在堆,而把这个对象的引用(指针)存储在栈。
Java虚拟机规范中,对这个区域规定了两种异常状况:
- 线程请求栈的深度大于虚拟机所允许栈的深度,将抛出Stack Overflow Error
- 如果虚拟机栈可以动态扩展且扩展时无法申请到足够的内存,会抛出OutOfMemoryError
这里注意的是如果递归的方法递归的太深很容易抛出上面两种异常,所以递归虽然写起来方便,但是性能会有所下降,并且容易抛出异常。
-Xss128k:设置每个线程的堆栈大小为128k,若不设置则为JVM默认值,此时默认可动态扩展。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
2.2.3 本地方法栈
线程私有;作用和 java 虚拟机栈相似,区别是 java 虚拟机栈为虚拟机执行 java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。Native方法指java调用非java代码(c++)的接口(jni)。
sayHello() 方法加了一个关键字 native ,就代表是一个native接口。执行这个方法时,会根据 jni.h来找到真正的C++编写的sayHello() 的实际函数。jni.h 是存在于 %JAVA_HOME%\include 下面的一个文件,另外还有个 %JAVA_HOME%\include\win32 下的jni_md.h。
2.2.4 java堆
线程共享;是java虚拟机所管理的内存中最大的一块,在虚拟机启动时创建,用于存放对象实例。java堆是垃圾收集器管理的主要区域。由于现在的垃圾回收算法多是分代收集,所以Java堆里面又可分为:新生代和老年代;再细致一点年轻代还能分为Eden区、From Survivor空间、To Survivor空间。并且根据Java虚拟机规范的规定:Java堆可以处于物理上不连续的内存空间中,只要逻辑上连续即可。注意:有实例没有被分配,且堆无法再扩展的时候会抛出OutOfMemoryError异常,虚拟机调优其实也主要关注的是这个区域。成员变量作为对象的属性,当然是放在堆里了。对象在堆里,对象中的内容就是各种字段。
- -Xms:初始堆大小(最小堆)。
- -Xmx:最大堆大小。
-Xms 和 -Xmx 设置成一致的值可以避免堆自动扩展。Oracle官方推荐堆的初始化大小与堆可设置的最大值一般是相等的,即 Xms = Xmx,因为起始堆内存太小(Xms),会导致启动初期频繁 GC,起始堆内存较大(Xmx)有助于减少 GC 次数
- -Xmn:年轻代大小(Sun官方推荐配置为整个堆的1/3)。对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置。
JVM内存大小 = 年轻代大小 + 老年代大小 + 永久代大小(perm)。永久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
- -XX:NewSize :指定新生代初始大小。
- -XX:MaxNewSize :指定新生代最大大小。
- -XX:NewRatio :是年老代 新生代相对的比例,比如NewRatio=2,表明年老代是新生代的2倍。老年代占了heap的2/3,新生代占了1/3。
- -XX:SurvivorRatio :配置的是在新生代里面Eden和一个Survivor比例。-XX:SurvivorRatio=8表示新生代的Eden占8/10,S1和S2各占1/10.
2.2.5 方法区
线程共享;方法区是JVM的一种规范,方法区在jdk1.7的实现是永久代,jdk1.8的实现是元空间Metaspace。可以选择不实现垃圾收集。方法区主要用于存储类字节码、静态变量、常量池、即时编译器编译后的代码等数据。
对于方法区的理解我们要注意以下几个方面:
- 方法区(Method Area)与堆一样,是各个线程共享的内存区域。
- 方法区在JVM启动的时候被创建,并且它实际的物理内存空间和虚拟机堆区一样都可以是不连续的。
- 方法区在JVM启动的时候被创建,并且它实际的物理内存空间和虚拟机堆区一样都可以是不连续的。
- 方法区的大小跟堆空间一样,可以选择固定大小或者可扩展。方法区的大小决定了系统可以保存多少个类。如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误,如java.lang.OutOfMemoryError:PermGen space或者java.lang.OutOfMemoryError:Metaspace。
以下情况都可能导致方法区发生OOM异常:加载大量的第三方jar包、Tomcat部署的工程过多(30~50个)或者大量动态地生成反射类。
JVM常量池(详细见下一章):
- class文件常量池:诞生于编译时,存在于class文件中,存放符号引用和字面量。
- 运行时常量池:诞生于JVM运行时,jdk1.7永久代被移除后存在于元空间,存放class文件元信息描述、引用类型数据、编译后的代码数据、类文件常量池(综合了每个class文件常量池)
- 字符串常量池:jdk1.6处于永久代,jdk1.7后处于堆区;存放字符串对象的引用
- 基本类型包装类常量池:位于堆区
2.2.5.1 永久代
存储已被 java 虚拟机加载的类字节码、静态变量、常量池、即时编译器编译后的代码等数据。jdk1.7 的 HotSpot 虚拟机中,已经把原本放在永久代的 字符串常量池 和 静态变量 转移到 java 堆;符号引用(Symbols) 转移到了本地内存(Native Memory)。jdk1.8中,原有的永久代改为了元空间(Metaspace),直接使用机器物理内存,因为原来的永久代内存大小不易评估,同时调优效率较低。永久代的垃圾收集是和老年代捆绑在一起的。
配置参数:
-XX:PermSize=300M 设置永久代大小
-XX:MaxPermSize=300M 设置永久代最大大小
2.2.5.2 元空间(Metaspace)
- 1、字符串存在永久代中,容易出现性能问题和内存溢出。
- 2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。而对于元空间来说类的元数据可以在本地内存(native memory)分配,所以其最大可利用空间是整个系统内存的可用空间。
- 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
- Oracle 可能会将HotSpot 与 JRockit 合二为一。
相关文章:

【JVM详解一】类加载过程与内存区域划分
一、简介 1.1 概述 JVM是Java Virtual Machine(Java虚拟机)的缩写,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相关…...

250207-MacOS修改Ollama模型下载及运行的路径
在 macOS 上,Ollama 默认将模型存储在 ~/.ollama/models 目录。如果您希望更改模型的存储路径,可以通过设置环境变量 OLLAMA_MODELS 来实现。具体步骤如下: 选择新的模型存储目录:首先,确定您希望存储模型的目标目录路…...

Win10 部署llama Factory 推荐教程和遇到的问题
教程 【大模型微调】使用Llama Factory实现中文llama3微调_哔哩哔哩_bilibili 大模型微调!手把手带你用LLaMA-Factory工具微调Qwen大模型!有手就行,零代码微调任意大语言模型_哔哩哔哩_bilibili 遇到问题解决办法 pytorch gpu国内镜像下载…...

如何在Android Studio中开发一个简单的Android应用?
Android Studio是开发Android应用的官方集成开发环境(IDE),它提供了许多强大的功能,使得开发者能够高效地创建Android应用。如果你是Android开发的初学者,本文将引导你如何在Android Studio中开发一个简单的Android应用…...

ubuntu下迁移docker文件夹
在 Ubuntu 系统中迁移 Docker 文件夹(如 Docker 数据存储文件夹 /var/lib/docker)到另一个磁盘或目录,通常是为了释放系统盘空间。以下是迁移过程的详细步骤: 1. 停止 Docker 服务 在进行迁移之前,必须停止 Docker 服…...

嵌入式面试题 C/C++常见面试题整理_7
一.什么函数不能声明为虚函数? 常见的不能声明为虚函数的有:普通函数(非成员函数):静态成员函数;内联成员函数;构造函数;友元函数。 1.为什么C不支持普通函数为虚函数?普通函数(非成员函数)只能被overload,不能被override,声明为虚函数也没有什么意思…...

使用OBS推流,大华摄像头 srs服务器播放
说明: ffmpeg可以推流,但是是命令行方式不太友好,还可以使用主流的OBS开源推流软件,可从官网Open Broadcaster Software | OBS 下载最新版本,目前很多网络主播都是用它做直播。该软件支持本地视频文件以及摄像头推流。…...

CSS 组合选择符详解与实战示例
在 Web 开发过程中,CSS 用于定义页面元素的样式,而选择器则帮助我们精确定位需要添加样式的元素。今天我们主要来讲解 CSS 中的组合选择符,它们能够根据 DOM 结构中元素之间的关系来选中目标元素,从而写出结构清晰、易于维护的 CS…...

Window系统通过Docker本地安装ollama和deepseek
在 Windows 系统上安装 Ollama 和 DeepSeek 的步骤如下: 安装 Ollama 安装 WSL(Windows Subsystem for Linux): 如果还没有安装 过WSL的(安装过的你直接跳过就行了),可以按照以下步骤进行安装&…...

镜头放大倍率和像素之间的关系
相互独立的特性 镜头放大倍率:主要取决于镜头的光学设计和结构,决定了镜头对物体成像时的缩放程度,与镜头的焦距等因素密切相关。比如,微距镜头具有较高的放大倍率,能将微小物体如昆虫、花朵细节等放大成像࿰…...

P3413 SAC#1 - 萌数
题目背景 本题由世界上最蒟蒻的 SOL 提供。 寂月城网站是完美信息教室的官网。地址:http://191.101.11.174/mgzd。 题目描述 蒟蒻 SOL 居然觉得数很萌! 好在在他眼里,并不是所有数都是萌的。只有满足“存在长度至少为 22 的回文子串”的数是萌的——也就是说,101 是萌…...

[RabbitMQ] RabbitMQ常见面试题
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...

Java运行时数据区
JVM主要流程包括三部分: 首先是 ClassLoard 类加载器,加载数据源文件到jvm当中然后将加载好的数据存放在运行时数据区最后由引擎进行解释和编译的工作 1.Java 内存区域: 1.1 程序计数器 程序计数器(Program Counter Register&a…...

【03】 区块链分布式网络
3-1 P2P网络 传统中心化网络由中央服务器保存全量数据。客户端之间无法直接连接,必须通过中央服务器作为桥梁。客户端必须和中央服务器建立连接后访问资源。客户端之间并无连通。 在P2P网络中通过将数据资源分散在网络各个节点中存储以及节点间交互连接࿰…...

【SQL server】关于SQL server彻底的卸载删除。
1.未彻底卸载删除SQL Server会出现的问题 如果没有彻底删除之前的SQL server,就可能会出现这个 当要安装新的实例的时候因为之前安装过sql server没有删除干净而导致下图问题,说实例名已经存在。 2.首先要先关闭服务 “开始R”可以快速进入运行&#…...

【含文档+PPT+源码】基于微信小程序的校园志愿者管理系统的设计与实现
项目介绍 本课程演示的是一款 基于微信小程序的校园志愿者管理系统的设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本…...

Docker入门(Windows)
视频链接:Docker | 狂神说 环境说明 Windows For Docker WSL2 概念 Docker是什么? 百度百科:百度百科 Docker 是一个开源的平台,它利用操作系统级虚拟化技术来打包和运行应用程序。通过使用容器化技术,Docker 提…...

深度求索(DeepSeek)的AI革命:NLP、CV与智能应用的技术跃迁
Deepseek官网:DeepSeek 引言:AI技术浪潮中的深度求索 近年来,人工智能技术以指数级速度重塑全球产业格局。在这场技术革命中,深度求索(DeepSeek)凭借其前沿的算法研究、高效的工程化能力以及对垂直场景的…...

Mac本地体验LM studio
博主很懒,不爱打字! 1、LM studio官网:LM Studio - Discover, download, and run local LLMs 2、下载DMG文件,安装 3、使用vscode工具,commandshiftH【全局替换功能】,选择目录/Applications/LM\ Studio…...

Spring Boot 线程池自定义拒绝策略:解决任务堆积与丢失问题
如何通过自定义线程池提升系统稳定性 背景 在高并发系统中,线程池管理至关重要。默认线程池可能导致: 资源浪费(创建过多线程导致 OOM)任务堆积(队列满后任务被拒绝)任务丢失(默认拒绝策略丢…...

解锁摄影潜能:全面解析相机镜头的选择与使用逻辑
目录 一、镜头分类:从焦距到用途的底层逻辑 (一)按焦距和视角分类(一级分类) (二)按特殊用途分类(一级分类) 二、参数解码:超越 “光圈越大越好” 的思维定…...

【Unity】从父对象中获取子对象组件的方式
1.GetComponentInChildren 用于获取对与指定组件或游戏对象的任何子级相同的游戏对象上的组件类型的引用。 该方法在Unity脚本API的声明格式为: public T GetComponentInChildren(bool includeInactive false) includeInactive参数(可选)…...

第六届MathorCup高校数学建模挑战赛-A题:淡水养殖池塘水华发生及池水自净化研究
目录 摘要 1 问题的重述 2 问题的分析 2.1 问题一的分析 2.2 问题二的分析 2.3 问题三的分析 2.4 问题四的分析 2.5 问题五的分析 3. 问题的假设 4. 符号说明 5. 模型的建立与求解 5.1 问题一的建模与求解 5.1.1 分析对象与指标的选取 5.1.2 折线图分析 5.1.3 相关性分析 5.1.4…...

webpack【初体验】使用 webpack 打包一个程序
打包前 共 3 个文件 dist\index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Webpack 示例&…...

<论文>DeepSeek-R1:通过强化学习激励大语言模型的推理能力(深度思考)
一、摘要 本文跟大家来一起阅读DeepSeek团队发表于2025年1月的一篇论文《DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning | Papers With Code》,新鲜的DeepSeek-R1推理模型,作者规模属实庞大。如果你正在使用Deep…...

公司配置内网穿透方法笔记
一、目的 公司内部有局域网,局域网上有ftp服务器,有windows桌面服务器; 在内网环境下,是可以访问ftp服务器以及用远程桌面登录windows桌面服务器的; 现在想居家办公时,也能访问到公司内网的ftp服务器和win…...

python爬虫--简单登录
1,使用flask框架搭建一个简易网站 后端代码app.py from flask import Flask, render_template, request, redirect, url_for, sessionapp Flask(__name__) app.secret_key 123456789 # 用于加密会话数据# 模拟用户数据库 users {user1: {password: password1}…...

人工智能浪潮下脑力劳动的变革与重塑:挑战、机遇与应对策略
一、引言 1.1 研究背景与意义 近年来,人工智能技术发展迅猛,已成为全球科技领域的焦点。从图像识别、语音识别到自然语言处理,从智能家居、智能交通到智能医疗,人工智能技术的应用几乎涵盖了我们生活的方方面面,给人…...

ESP32-S3驱动步进电机以及梯形加减速库调用
一、硬件连接说明 电机与驱动器连接: 42BYGH39-401A步进电机有4根引线,分别连接到驱动器(如TB6600)的电机接口上。 电机引脚A、A-、B、B-分别连接到驱动器对应的电机接口。 驱动器与ESP32-S3连接: ESP32-S3的GPIO引脚…...

【CubeMX+STM32】SD卡 文件系统读写 FatFs+SDIO+DMA
本篇,将使用CubeMXKeil,创建一个SD卡的 FatFSSDIODMA 文件系统读写工程。 目录 一、简述 二、CubeMX 配置 FatFSSDIO DMA 三、Keil 编辑代码 四、实验效果 实现效果,如下图: 一、简述 上两篇,已循序渐进讲解了SD、…...