【JVM】JVM基础教程(一)
目录
初识JVM
JVM是什么?
JVM的功能
解释、即时编译和运行
内存管理
常见的JVM
JVM虚拟机规范
HotSpot的发展历程
JVM的组成
字节码文件详解
应用场景
以正确姿势打开字节码文件
编辑字节码文件的组成
基本信息
Magic魔数
主副版本号
常量池
接口
字段
方法
案例分析
案例分析
案例分析
属性
常用工具
javap -v命令
IDEA插件-jclasslib
阿里Arthas
入门使用
监控面板
查看字节码信息
案例分析
类的生命周期(重点)
应用场景
生命周期概述
加载阶段
查看内存中的对象
连接阶段
验证阶段
版本号的检测
准备阶段
静态变量分配内存&初始值
解析阶段
初始化阶段
何时初始化?
clinit指令
初始化的要点
案例分析
案例分析
案例分析
案例分析
常量折叠
初识JVM
JVM是什么?
JVM(Java Virtual Machine),中文名Java虚拟机
JVM就是一款软件,用来运行Java字节码文件
将字节码文件【解释】(配合JIT、AOT编译器)成【机器码】,计算机能直接运行机器码
(机器码是计算机能够直接运行的指令集,机器码由二进制数字组成,通常以0和1的形式表示。这些指令被处理器(CPU)解码和执行)
关于JIT和AOT,可以看我另一篇博客:【Java基础面试题003】Java的JIT | AOT是什么?_java jit面试-CSDN博客
JVM的功能
JVM 包含内存管理、解释执行虚拟机指令、即时编译三大功能
解释、即时编译和运行
- 将字节码文件,解释+即时编译成机器码,交给计算机执行
- 即时编译,对热点代码进行优化,提升执行效率
(无论JVM到底是编译字节码还是解释字节码,最终都是生成机器码)
- 由于JVM需要实时解释虚拟机指令,所以Java语言如果不做任何优化,性能不如C、C++等语言
- JVM提供了即时编译(JIT)进行性能的优化,尤其是C2编译器,最终能勉强接近C、C++的运行性能(接近,还是勉强~~),在特性场景下有机会实现超越
- Java需要实时解释,主要是为了支持跨平台特性
内存管理
- 自动给对象、方法等分配内存
- 自动的垃圾回收机制,回收不再使用的对象
常见的JVM
常见的JVM有HotSpot、GraalVM、OpenJ9等,另外DragonWell龙井JDK也 提供了一款功能增强版的JVM。其中使用最广泛的是HotSpot虚拟机。
看得出Java的生态真的很好,不过我用的JDK是这一家的
Adoptium Eclipse Temurin:Home | Adoptium
JVM虚拟机规范
官网地址:Java SE Specifications (oracle.com)
《Java虚拟机规范》由Oracle制定,内容主要包含了Java虚拟机在设计和实现时需要遵守的规范,主 要包含class字节码文件的定义、类和接口的加载和初始化、指令集等内容。
《Java虚拟机规范》是对虚拟机设计的要求,而不是对Java设计的要求,也就是说虚拟机可以运行在 其他的语言比如Groovy、Scala生成的class字节码文件之上。
HotSpot的发展历程
JVM的组成
字节码文件详解
应用场景
- 面试回答
学习字节码文件的组成可以更深入的理解Java代码,说点实际的,最起码面试的时候有用
比如下列面试题:
如果从Java语法层面回答这个题,面试官可能会觉得你的道行不深,如果从字节码文件中的字节码指令来回答这个题,面试官可能会觉得你对JVM的了解还不错
这里给个例子复习一下后自增
(i++先返回值用来赋值操作,后自增,但是自增的值"丢失"了,没有被保存下来,可以理解为自增操作被赋值操作覆盖了)
int i = 0;i = i++;System.out.println(i); // 0int j = 0;j = ++j;System.out.println(j); // 1
- 解决版本冲突
- 系统升级
以正确姿势打开字节码文件
一般的记事本,包括高级记事本,打开字节码文件,会部分乱码,毕竟.java文件编译成.class文件用的编码格式有很多,不单纯是单一的UTF8啥的
为了更直观查看.class文件,可以用下面这一款工具【jclasslib】
官网:GitHub - ingokegel/jclasslib: jclasslib bytecode editor is a tool that visualizes all aspects of compiled Java class files and the contained bytecode.
版本号:v6.0.5

字节码文件的组成
下面围绕这段代码进行分析字节码文件的组成
public interface Test {void printOneLine(int age);
}
public class MyTest implements Test{// 常量private static final String str1 = "黄小桃";private static final String str2 = "黄小桃";private int age;public MyTest(){}public MyTest(int age){this.age = age;}public int getAge(){return this.age;}@Overridepublic void printOneLine(int age){System.out.println(str1 + "那年" + age + "岁");}public static void main(String[] args) {MyTest myTest = new MyTest(19);myTest.printOneLine(myTest.getAge());}
}
基本信息
Magic魔数
- 文件是无法通过文件扩展名来确定文件类型的,文件扩展名可以随意修改,不影响文件的内容
- 软件使用文件的头几个字节(文件头)去校验文件的类型,如果软件不支持该种类型就会出错
- Java字节码文件中,将文件头称为Magic魔数
(魔数:是指文件的前四个字节,用于标识该文件确实是一个有效的Java字节码文件。这个魔数的值是固定的。魔数帮助系统快速识别文件,不需要检查文件内容)
下面给一个魔数的例子:
0000: CAFEBABE (魔数) 0004: 0000 0034 (次版本号、主版本号) ...
主副版本号
就是编译字节码文件的JDK版本号
- 主版本号用来标识大版本号,JDK1.0 - 1.1使用了45.0 - 45.3,JDK1.2是46之后没升级一个大版本就加1;
- 副版本号是当主版本号相同时作为区分不同版本的标识,一般只需要关心主版本号
版本号的作用主要是判断当前字节码的版本和运行时的JDK是否兼容
案例:主版本号不兼容错误
两种解决方案:
- 升级JDK版本(容易引发其他的兼容性问题,需要大量的测试)
- 将第三方依赖的版本号降低或者更换依赖,以满足JDK版本的需求(建议采用)
常量池
避免重复定义相同的内容,节省空间
- 常量池中的数据都有一个编号,编号从1开始。在字段或者字节码指令中通过编号可以快速的找到对应的数据
- 字节码指令中通过编号引用到常量池的过程称之为符号引用
查看源码,有两个常量的内容一致
查看字段,发现有三个字段,常量值索引为#21
根据索引查看常量内容
补充说明:
如果常量名与常量内容相同,那么加载到常量池中,为了节省空间,将直接指向内容,而非先指向类型再指向内容
接口
字段
方法
字节码中的方法区是存放字节码指令的核心位置,字节码指令的内容存放在方法的Code属性中
方法部分,换一个代码案例
public class MyTest {public static void main(String[] args) {int i = 0;int j = i + 1;}
}
这些指令是什么意思呢?可以查看源文档
左键点击指令,查看规范
字面意思就是将这个指令放入操作栈,至于操作栈,下面我会说明
局部变量表是根据源代码从上到下、从右到左执行的顺序,加载到局部变量表的
案例分析
初始环境
先根据顺序加载所有局部变量到局部变量数组中
这个就是局部变量表
iconst_0
对于int i = 0;先将常量池的常量0加载到操作数栈
istore_1
对于int i = 0;再将操作数栈中的0存入局部变量数组下标为1的局部变量i中
iload_1 & iconst_1
对于int j = i + 1;将局部变量数组下标为1的局部变量i的值(0)加载到操作数栈, 并且将常量1加载到操作数栈
iadd
对于int j = i + 1;对操作数栈中的常量们进行加法运算
istore_2
对于int j = i + 1;将操作数栈中的常量值存入局部变量数组[2]的局部变量j中
return
结束方法(main方法)
JVM清空操作数栈,局部变量数组被销毁,内存空间释放
现在再来分析一个案例
案例分析
public class MyTest {public static void main(String[] args) {int i = 0;i = i++;}
}
初始环境
iconst_0
对于int i = 0;先加载常量值0到操作数栈中
istore_1
对于int i = 0;再将常量值0弹入到局部变量i
iload_1
对于i = i++;从语法上看,是先执行i++,将局部变量i的值加载到操作数栈中
iinc 1 by 1
查看源文档
所以是用常数1增加局部变量i
注意看细节,这次的加法是在局部变量中运行的,这也是回答面试的关键点
istore_1
将操作数栈的常量值存入局部变量i,也就是将0替换了1,导致最终结果还是0
return
JVM清空操作数栈,局部变量数组被销毁,内存被释放
最后回答,这种从字节码指令层面的回复,会比Java语法层面的"先增后增"回复好一些
Java语法层面说 n = i++是先返回值给n,再自增,对应到字节码指令层面,就是先iload_ 到操作数栈,n获取的是操作数栈中的数,再 iinc 1 by 1自增
如果是++i
案例分析
public class MyTest {public static void main(String[] args) {int i = 0, j = 0, k = 0;i++;j = j + 1;k += 1;}
}
这么看的话,性能排序是 (i++) = (k+=1) > (j = j + 1)
属性
常用工具
javap -v命令
- javap是JDK自带的反编译工具,可以通过控制台查看字节码文件的内容。适合在服务器上查看字节码文件内 容
- 直接输入javap查看所有参数。
- 输入javap -v 字节码文件名称 查看具体的字节码信息。(如果jar包需要先使用 jar –xvf命令解压)
IDEA插件-jclasslib
这款软件也有idea插件版本,建议开发时使用IDEA插件版本
阿里Arthas
Java应用诊断器,一款宝藏工具,这里我必须吹一波阿里云,真的很棒!下文会频繁的使用这个工具
简介 | arthas (aliyun.com)
链接:https://arthas.aliyun.com/arthas-boot.jar
还有很多中下载安装方式,自己查看官网
入门使用
public class MyTest {public static void main(String[] args) throws Exception{while (true){Thread.sleep(1000);}}
}
这个代码死循环睡眠,模拟程序持续运行
运行jar包
会显示所有Java相关进程,我们要用第4个
输入4,回车
看到当前程序的进程是2388,然后下面的所有命令都只对2388这个进程生效
监控面板
arthas的功能很多,本章节先学习监控面板&&查看字节码信息这两个功能,其余的后面可能会出现
查看官方文档
dashboard -i 2000 -n 3
查看字节码信息
dump命令
dump -d [存放路径] [目标类的全限定名]
jad命令
反编译命令
案例分析
类的生命周期(重点)
类的生命周期描述了一个类加载、使用、卸载的整个过程
类的生命周期是高频面试、笔试点,也是后续大量知识点的基础部分,很重要
比如下列的输出结果是:
public class MyTest {public static void main(String[] args) {System.out.print("A");new MyTest();new MyTest();}public MyTest(){System.out.print("B");}{System.out.print("C");}static{System.out.print("D");}
}
public class MyTest {public static void main(String[] args) {new BO2();System.out.println(BO2.a);}
}class AO2{static int a = 0;static {a = 1;}
}class BO2 extends AO2{static {a = 2;}
}
应用场景
生命周期概述
加载阶段
1.加载(Loading)阶段的第一步是类加载器根据类的全限定名,通过不同渠道以二进制流的方式获取字节码信息。
开发者可以使用Java代码拓展不同的渠道
2.类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到方法区中
3.字节码信息加载到方法区中之后,JVM在方法区生成一个InstanceKlass对象,保存类的所有信息,里面还包含实现特定功能比如多态的信息
4.同时,JVM还会在堆中生成一份与方法区中数据类似的java.lang.Class对象
作用是:在Java代码中去获取类的信息&&存储静态字段的数据(JDK8及之后)
对于开发者来说,只需要访问堆中的Class对象而不需要访问方法区中所有信息,这样JVM就能很好地控制开发者访问数据的范围
查看内存中的对象
推荐使用JDK自带的hsdb工具查看JVM内存信息。
在JDK/lib目录下
进到lib目录,启动命令
java -cp sa-jdi.jar sun.jvm.hotspot.HSDB
输入java进程PID连接,查看虚拟机内存信息
连接阶段
验证阶段
1.连接(Linking)阶段的第一个环节是验证,验证的主要目的是检测Java字节码文件是否遵守了《Java虚拟机规范》中的约束。这个阶段一般不需要开发者参与
2.主要包含如下四个部分,具体详见《Java虚拟机规范》:
- 文件格式验证,比如文件是否以0xCAFEBABE开头,也就是魔数,主次版本号是否满足当前Java虚拟机版本要求
- 元信息验证,例如类必须有父类(则super不能为空)
- 验证程序执行指令的语义,比如方法内的指令执行中跳转到不正确的位置
- 符号引用验证,例如是否访问了其他类中private的方法等
版本号的检测
Hotspot JDK8中虚拟机源码对版本号检测的代码如下,你能读懂它的含义吗:
准备阶段
静态变量分配内存&初始值
- 准备阶段为静态变量(static)分配内存并设置初始值
- 注意:本章涉及到的内存结构只讨论JDK8及以后的版本
- 准备阶段只会给静态变量赋初始值,而每一种基本数据类型和引用数据类型都有其初始值
- final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值,而没有初始化阶段
解析阶段
解析阶段主要是常量池中的符号引用替换为内存地址直接引用
符号引用就是在字节码文件中使用编号来访问常量池中的内容
直接引用不再使用编号,而是使用内存中地址进行访问具体的数据
初始化阶段
准备阶段:为静态变量(static)分配内存&设置初始值
初始化阶段:为静态变量(static)赋值,执行静态代码块中的代码
注意两者的区别,途中value的最终值应该是1,而不是0
初始化阶段会执行字节码文件中clinit部分的字节码指令。
public class MyTest {public static int value = 1;static{value = 2;}public static void main(String[] args) {}
}
重点来了
何时初始化?
(访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化。)
1.调用Class.forName(String className)。
2.new一个该类的对象时。
3.执行Main方法的当前类。
4.直接引用静态变量或静态方法
5.使用反射机制访问类的构造器(例如
Constructor<?> constructor = Class.forName("A").getDeclaredConstructor();
)6.静态导入(比如
import static ...
)7.如果有一个枚举类型,并且在其中使用了静态代码块,访问任何枚举值时也会导致整个枚举类被加载,这样其静态代码块会被执行。
clinit指令
clinit指令在特定情况下不会出现,比如:如下几种情况是不会进行初始化指令执行的。
1.无静态代码块且无静态变量赋值语句。
2.有静态变量的声明,但是没有赋值语句。
3.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。
初始化的要点
数组的创建不会导致数组中元素的类进行初始化
final修饰的变量如果赋值的内容需要执行指令才能得出结果,会执行clinit方法进行初始化
案例分析
面试题一
public class MyTest {public static void main(String[] args) {System.out.print("A");new MyTest();new MyTest();}public MyTest(){System.out.print("B");}{System.out.print("C");}static{System.out.print("D");}
}
先执行clinit部分,也就是static代码块
先搞清楚新指令的作用,查看文档
getstatic
从字节码中获取静态字段值,载入操作栈顶中
ldc
将常量池中的值载入操作数栈中
invokevirtual
处理栈顶操作
OK,现在分析字节码指令
第一行,通过
getstatic
获取System.out
的PrintStream
对象,并将其放入操作数栈顶。也就是定义中的获取静态字段(System.out)的值(PrintStream对象)
这个PrintStream对象就是用来打印的
第二行,从常量池取出字符串D(将常量存入常量池就编译源代码的时候做的,并不需要什么显式的字节码指令,这里可以直接从常量池获取),取出后加载到操作数栈上
第三行,invokevirtual调用printStream类的print方法,打印栈顶的字符串D
第四行,return结束静态代码块
执行main方法前,首先初始化类的static代码块
输出结果:D
现在开始执行main方法
前三行
输出结果:A
第四行,new创建MyTest类的实例,是对象的一个引用(此时对象还没有初始化),也就是所谓的this,还将此引用推送到操作数栈中
第五行,dup复制一份对象的引用,放在操作数栈顶上(每次调用对象都会dup一次,应该是为了每个引用互不影响)
第六行,invokespecial调用构造方法开始初始化刚刚new出来的空对象
看3 - 5行,打印字符串C
看6 - 8行,打印字符串B
书接上回
第七行,pop弹出栈顶的对象引用,对象引用处理完毕
8 - 11行,重复一次上述操作
输出结果:CBCB
案例分析
public class MyTest {public static void main(String[] args) {System.out.println(BO2.a);}
}class AO2{static int a = 0;static {a = 1;}
}class BO2 extends AO2{static {a = 2;}
}
分析:初始化的条件有三个,上面我记的有
所以B02.a这一行就先获取的是父类A02的静态变量a,执行了父类A02的static代码块,将a赋值为1此时字节码执行return结束了静态代码块的初始化操作
这时不再执行子类B02的static代码块,理由是,初始化操作通过return指令已经结束,如果要执行子类B02的static代码块,需要重新初始化,比如可以加一行new B02();
new的操作会再次访问B02的父类A02,发现AO2的静态代码块已经加载过了,不会再触发了,于是开始加载子类的,所以会赋值a为2
案例分析
这个好理解,new的数据,分配了10个空间,每个元素都在准备阶段设置了初始值,A类的默认值是null,所以这个数组的元素全是null
再来复习一下初始化的条件
案例分析
public class MyTest {public static void main(String[] args) {System.out.println(A.a);}
}class A{// public static final int a = 1;public static final int a = Integer.valueOf(1);static {System.out.println("A类的静态代码块初始化");}
}
常量折叠
引入一个概念,编译时常量,A类的public static final int a = 1;
JVM做了优化,在编译时编译器直接将a的值嵌入到代码中,不需要运行时初始化了,直接跳过了初始化阶段
public class MyTest {public static void main(String[] args) {System.out.println(A.a);}
}class A{public static final int a = 1;
// public static final int a = Integer.valueOf(1);static {System.out.println("A类的静态代码块初始化");}
}
仔细对比字节码指令,发现第二种,压根没有getstatic A的clinit初始化操作,而是iconst_1直接从常量池把常量1拿到了操作数栈中,初始化操作直接跳过了
下一章:【JVM】JVM基础教程(二)-CSDN博客
相关文章:

【JVM】JVM基础教程(一)
目录 初识JVM JVM是什么? JVM的功能 解释、即时编译和运行 内存管理 常见的JVM JVM虚拟机规范 HotSpot的发展历程 JVM的组成 字节码文件详解 应用场景 以正确姿势打开字节码文件 编辑字节码文件的组成 基本信息 Magic魔数 主副版本号 常量池 接口…...
Python并发编程全解析
一、前言 在现代开发中,并发编程是提高性能、响应速度的关键技术之一。Python提供了多种实现并发的方式,如多线程、多进程和异步IO。本篇文章将逐一解析这些技术,探讨其适用场景,并通过代码示例帮助理解。 二、并发编程的核心概念 1. 并发与并行 并发:任务在时间片上交替…...

大语言模型应用Text2SQL本地部署实践初探
自从两年前OpenAI公司发布ChatGPT后,大模型(Large Language Model,简称LLM)相关技术在国内外可谓百家争鸣,遍地开花,在传统数据挖掘、机器学习和深度学习的基础上,正式宣告进入快速发展的人工智能(Artificial Intellig…...

每日十题八股-2024年12月7日
1.说说hashmap的负载因子 2.Hashmap和Hashtable有什么不一样的?Hashmap一般怎么用? 3.ConcurrentHashMap怎么实现的? 4.分段锁怎么加锁的? 5.分段锁是可重入的吗? 6.已经用了synchronized,为什么还要用CAS呢…...

VTK编程指南<三>:基于VTK入门程序解析来理解VTK基础知识
1、VTK入门程序 下面是一个完整的Vtk入门程序,我们基于这个程序来对VTK的基本知识进行一个初步了解。 #include <iostream>#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2 VTK_MODULE_INI…...

PyQt5快速开发与实战
PyQt5快速开发与实战相关资源 PyQt5快速开发与实战配套代码资源获取 PyQt5快速开发与实战 第一个要跟大家分享的就是的《PyQt5快速开发与实战》。该书既涵盖了 PyQt5 的基础知识,又包含了实战应用技巧,对 PyQt5 的基本概念和技术细节进行了详细阐述&…...

SpringBoot 开源停车场管理收费系统
一、下载项目文件 下载源码项目文件口令: 【前端小程序地址】(3.0):伏脂火器白泽知洞座/~6f8d356LNL~:/【后台管理地址】(3.0):伏脂火器仇恨篆洞座/~0f4a356Ks2~:/【岗亭端地址】(3.0):动作火器智汇堂多好/~dd69356K6r~:/复制口令…...
cmake: error while loading shared libraries: libssl.so.1.1
在ubuntu22.04中编译c文件时出现如下错误: cmake: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory 解决办法:1.进网站下载对应的.deb文件,链接为:https://sec…...

部署loki,grafana 以及springcloud用法举例
文章目录 场景docker 部署grafanadocker-compose部署loki维护配置文件 local-config.yaml维护docker-compose.yml配置启动 grafana 添加loki数据源springcloud用法举例查看loki的explore,查看日志 场景 小公司缺少运维岗位,需要研发自己部署日志系统,elk…...

后端-编辑按钮的实现
编辑一共要实现两步: 1.点击编辑蹦出来一个弹窗,此时需要回显,根据id查出来这条数据 2.修改某些值之后点击保存的时候调用修改的接口 根据id查询的时候正常操作 修改值的时候要注意一些问题 mapper层的Employee和impl层的接收实体不一样...
uniapp中的@tap与@click:点击事件的微妙差异
在uniapp的开发过程中,我们经常会遇到两种点击事件:tap和click。虽然它们都是点击事件,但在实际使用中却存在一些微妙的差异。本文将详细解析这两种事件的区别,帮助开发者更好地理解和应用。 首先,让我们来看看它们的…...
Uniapp的vue、nvue、uvue后缀名区别
在 UniApp 中,.vue、.nvue 和 .uvue 是不同的文件后缀名,每个文件格式的使用场景和兼容性略有不同。下面是每个文件后缀的详细解释以及它们的兼容性: 1. .vue 文件 定义:.vue 是标准的 Vue 单文件组件格式,主要用于基…...

完美解决Qt Qml窗口全屏软键盘遮挡不显示
1、前提 说明:我使用的是第三方软键盘 QVirtualKeyboard QVirtualKeyboard: Qt5虚拟键盘支持中英文,仿qt官方的virtualkeyboard模块,但使用QWidget实现。 - Gitee.com 由于参考了几篇文章尝试但没有效果,链接如下: 文章一:可能…...
寄存器、缓存、内存三者关系
寄存器、缓存、内存三者关系: 按与CPU远近来分,离得最近的是寄存器,然后缓存(CPU缓存),最后内存。CPU计算时,先预先把要用的数据从硬盘读到内存,然后再把即将要用的数据读到寄存器。于是 CPU<--->…...

九、RNN的变体
RNN的变体 前言一、长短期记忆网络(LSTM)1.1 LSTM结构分析1.1.1 遗忘门1.1.1.1 遗忘门结构图与计算公式1.1.1.2 结构分析1.1.1.3 遗忘门的由来1.1.1.4 遗忘门的内部演示 1.1.2 输入门1.1.2.1 输入门结构图与计算公式1.1.2.2 结构分析1.1.2.3 输入门的内部…...
高级java每日一道面试题-2024年12月07日-JVM篇-如何选择垃圾收集器?
如果有遗漏,评论区告诉我进行补充 面试官: 如何选择垃圾收集器? 我回答: 在Java高级面试中,选择垃圾收集器(Garbage Collector,GC)是一个重要且常见的议题。选择合适的垃圾收集器对于优化应用程序的性能至关重要。以下是对如何…...

棋牌游戏项目ctrl + c无法退出进程问题
棋牌游戏项目ctrl c无法退出进程问题 运行的服务为 user , 启动命令为 cd user && go run main.go启动之前先加入调试语句 在 go func() { metric.Serve(...) } 打日志在 app.Run(...) 打日志 user/main.go var configFile flag.String("config", "…...

论文概览 |《Urban Analytics and City Science》2023.03 Vol.50 Issue.3
本次给大家整理的是《Environment and Planning B: Urban Analytics and City Science》杂志2023年3月第50卷第3期的论文的题目和摘要,一共包括18篇SCI论文! 论文1 A new kind of search 一种新型的搜索 【摘要】 ChatGPT (2022) was first launched o…...

前端知识1html
VScode一些快捷键 Ctrl/——注释 !——生成html框架元素 *n——生成n个标签 直接书写html的名字回车生成对应的标签 常见标签 span: <span style"color: red;">hello</span> <span>demo</span> span实现: 标题…...

Vue03
目录 一、今日目标 1.生命周期 2.综合案例-小黑记账清单 3.工程化开发入门 4.综合案例-小兔仙首页 二、Vue生命周期 三、Vue生命周期钩子 四、生命周期钩子小案例 1.在created中发送数据 六、工程化开发模式和脚手架 1.开发Vue的两种方式 2.Vue CLI脚手架 基本介绍…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...