第6章 类文件结构《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》
第6章 类文件结构
代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步。
6.1 概述
老师说过,计算机只认识0和1,所以我们写的程序需要被编译器翻译成由0和1构成的二进制格式才能被计算机执行。
但十多年过去了,把程序编译成二进制本地机器码(Native Code)不是唯一选择,很多语言选择与操作系统和机器指令集无关的、平台中立的格式作为存储格式。
6.2 无关性的基石
指令集只有x86,系统只有Windows,也许不会有Java语言的出现。
所有平台支持**字节码(Byte Code)**构成平台无关性的基石。
6.3 Class类文件的结构
Class文件结构稳定,很多年来没咋变化,后面的版本兼容前面。
Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在文件之中,中间没有添加任何分隔符,整个内容全部是程序运行的必要数据,没有空隙存在。
根据规范,Class文件格式采用类似于C语言结构体的伪结构来存储数据。
包含两种数据类型:“无符号数"和"表”.
- 无符号数属于基本的数据类型,以u1,u2,u4,u8来分别代表1个字节、2个字节、4个字节、8个字节的无符号数(没有负数),可以描述数字、索引引用、数量值或UTF-8编码的字符串值。
- 表由多个无符号数或其他表作为数据项的复合数据类型,便于区分,表的命名以"_info"结尾,表用于描述有层次关系的复合结构的数据,整个Class文件本质上视为一张表,看如下排列顺序。
无论是无符号数或表,描述同一类型但数量不定的多个数据时,会使用前置的容量计数器加若干连续的数据项的形式,称为"集合"。
数据行顺序和数量都是严格定义,不允许改变。
6.3.1 魔数与Class文件的版本
每个Class文件头4个字节被称为魔数(Magic Number),作用是确定此文件是否是一个能被虚拟机接受的Class文件。GIF,JPEG等文件头中都存有魔数。
魔数值为:0xCAFEBABE(咖啡宝贝,设计类的大佬有趣,暗指Java是一种咖啡)。
5,6字节是次版本号(Minor Version),7,8是主版本号(Major Version)。
简单Java代码编译成Class来分析
public class TestClass {private int m;public int inc() {return m + 1;}}
Ctrl+1,0等转换为十进制或十六进制。
主版本为61,减去44,JDK为17,可支持6-17的代码。
基本上JDK12之后,主要主版本,次版本都是0.
6.3.2 常量池
与其他项目关联最多,空间也最大。
常量池入口放一个常量池计数值(constant_pool_count),从1开始,不是0.
这里是22,则有21项常量。第0项特殊考虑,表示不引用任何一个常量池项目,可以把索引设为0.
常量池中存放两大类常量:字面量(Literal),不用变量保存,是固定值,int a = 10,10是字面量和符号引用(Symbolic References),例如方法名a调b对象,存b的方法printMessage,加载类后内存中解析为直接引用(内存地址或句柄),这就是动态链接。
字面量接近为常量概念,符号引用是编译原理的概念。
包含的常量:
- 模块导出的或开发的包(Package)
- 类和接口的全名(Fully Qualified Name)
- 字段的名称和描述符(Descriptor)
- 方法的名称和描述符
- 方法句柄和方法类型(Method Handle、MethodType、Invoke Dynamic)
- 动态调用点和动态常量(Dynamically-Computed Call Site、Dynamically-Computed Constant)
字段描述符
- 定义:字段描述符是一种特定的字符串格式,用于在字节码层面描述字段的数据类型。它遵循特定的规则,不同的数据类型有不同的表示方式。这种描述方式使得 Java 虚拟机(JVM)能够准确识别字段的数据类型,即使在字节码中无法直接看到像 Java 代码中那样直观的类型声明。
- 规则及示例:
- 基本数据类型:
boolean
用Z
表示。byte
用B
表示。char
用C
表示。short
用S
表示。int
用I
表示。long
用J
表示(由于long
类型占 64 位,在描述符中需要特殊标识)。float
用F
表示。double
用D
表示(同理,double
类型占 64 位,有特定描述符)。
- 引用数据类型:类和接口的描述符是其全限定名,不过斜杠(
/
)代替点(.
)作为包名分隔符,并使用L
作为前缀和分号(;
)作为后缀。例如,java.lang.String
的描述符是Ljava/lang/String;
。 - 数组类型:对于数组,描述符以左方括号(
[
)开头,后面跟着元素类型的描述符。例如,int[]
的描述符是[I
,String[]
的描述符是[Ljava/lang/String;
。
- 基本数据类型:
常量池中每一项常量都是一个表,共17种,仔细看标志不连续。
这17种没有共性,要逐项讲解。
整体计算常量就不手动了,这里通过JDK的bin目录中,javap工具。
javap -verbose .\TestClass.class
LineNumberTable,LocalVariableTable,this,SourceFile等都是编译器生成的。
后面的字段表,方发表,属性表会引用的。
6.3.3 访问标志
常量池结束后,接下来的2个字节代表访问标志(access_flags),此标志用于类或接口的访问信息。
1111 0110 0011 0001,按位存储,16个标志位,定义了9个,其他都为0.
上面的TestClass案例,访问标志为 0000 0000 0010 0001,16进制0x0021。
结果也确实如此。
6.3.4 类索引、父类索引和接口索引集合
类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,而接口索引集合(interfaces)是一组u2类型的数据集合。这三项能决定类型的继承关系。
类索引和父类索引指向常量池#1,#3,则是两个类的类名,接口为0表示没有实现的接口。
6.3.5 字段表集合
字段表(field_info)用于描述接口或者类中声明的变量。
字段(Field):包含类变量(静态变量),实例变量(普通变量),并不包括方法声明的局部变量(这些变量在栈中加载,引用的实例也在堆中)。
可以修饰字段的有public,private,pretected,static,final,volatile(并发可见),transient,数据类型。
修饰符都是布尔值适合用标志位来表示。
字段的名字通过引用常量池中的常量来描述。
access_flags
字段修饰符与类修饰符非常类似,u2的16位标志位。
0101 0000 1101 1111,9位有效的1,从右往左数,1,2,3只能三选一,5,7位不能同时为1。接口1,4,5位必须是1,也就是public static final InterA{}。
name_index
长度u2,表示堆常量池索引的引用,代表字段的简单名称。
全限定名:“a/b/c/TestClass”,把类中".“换成”/“,使用时最后加”;"。
简单名称:没有修饰的字段和方法的名称,int()方法和m字段,简单名分别为inc和m。
descriptor_index
字段描述符:来描述字段的数据类型,方法参数列表,返回这和是否无返回值以及返回值类型,也就是如下。
具体前面也讲过了。
二维字符串数组:[[Ljava/lang/String;
整型数组:[I。
方法void inc():()V,V这里是无返回值void的意思。
long add(int a,int b,int c):(III)J
1,2,5,6分别代表字段数是1个,访问标志为私有的ACC_PRIVATE,名称的常量池索引5为m,描述符的常量池索引6为I,即int型,那么整体为:private int m; 。
attribute_info后面讲
如果final static int m = 123;,可能会有ConstantValue的属性,值指向常量123。
总结:Java中字段无法重载,但在字节码文件中,理论上字段描述符不同,字段重名是合法的,实际中也没人这么干。
6.3.6 方法表集合
方法表与字段表结构类似,仅在访问标志和属性表集合有所区别。
由于volatile关键字和transient关键字不能修饰方法,所以方法表中的访问标志中没有ACC_VOLATILE标志和ACC_TRANSIENT标志。
与之相对,synchronized,native,strictfp和abstract关键字可以修饰方法,方法表中也相应增加ACC_SYNCHRONIZED,ACC_NATIVE,ACC_STRICTFP和ACC_ABSTRACT标志。
方法的定义可以通过访问标志、名称索引、描述符索引来表达清楚。
但方法里面的代码哪里去了?Java代码经过Javac编译器编译成字节码指令之后,存放在方法属性表集合中一个名为"Code"的属性里面,属性表作为Class文件格式中最具拓展性的一种数据项目。
具体自己查吧,我的眼睛已经花了。
6.3.7 属性表集合
Class文件对其他数据项要求严格,对属性表集合的限制稍微宽松一些。
Java SE 12版本中,预定义属性已经增加到29项。
对于每一个属性,名称都要从常量池中引用一个CONSTANT_Utf8_info类型的常量来表示。属性值结构完全自定义,只需要通过一个u4的长度属性去说明属性值所占用的位数即可。
1.Code属性
Java程序方法体里面的代码经过Javac编译器处理之后,最终变为字节码指令存储在Code属性内,Code属性出现在方法表的属性集合中,并非所有方法表必须存在这个助兴,接口和抽象类中的方法就不存在Code属性。
max_stack代表了操作数栈(Operand Stack)深度的最大值,在方法执行的任意时刻,操作数栈都不会超过这个深度,虚拟机运行的时候需要根据这个值类分配栈帧(Stack Frame)中的操作栈深度。
max_locals代表了局部变量表所需的存储空间,这里的单位是变量槽(Slot),变量是虚拟机为局部变量分配内存使用的最小单位。byte,char,float,int,short,boolean,returnAddress等长度不超过32位的数据类型,每个局部变量占用一个变量槽,double和long的64位数据类型需要2个变量槽。
这里需要查查什么是栈帧,槽等概念。
接下来的就更细了,没耐心,脑子乱,等待后续更新吧。。。
2.Exceptions属性
等等吧
6.4 字节码指令简介
操作码(Opcode):Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字。
操作数(Operand):跟随在操作数后零到多个代表此操作所需的参数。
Java虚拟机采用面向操作数栈而不是面向寄存器的架构。
大多数指令不包含操作数,只有一个操作码,指令参数都存放在操作数栈中(参考计算器的设计原理)。
劣势:Class文件格式放弃编译后代码的操作数长度对齐,处理超过1字节的数据时,在运行时从字节中重建出具体数据的结构。某种程度上损失了一些性能。
优势:指令集操作数码不超过256条,放弃了操作数长度对齐,省掉大量的填充和间隔符号,尽可能获得短小精干的编译代码。
不考虑异常的话,解释器可以使用下面这个模型来进行有效正确的工作:
6.4.1 字节码与数据类型
多数指令包含操作所对应的数据类型信息。
iload用于从局部变量表中加载int型的数据到操作数栈。
fload加载的则是float类型的数据。
int,long,short,byte,char,float,double都是首字母,引用类型reference是a。
arraylength指令,后面的操作数只能是一个数组类型的对象。
并非每种数据类型和每一种操作都有对应的指令,有些指令可将不支持的类型转为支持的类型。
例如:load指令有操作int类型的Iload,但没有操作byte的同类指令。
Java虚拟机指令集支持的数据类型
编译器或运行期将byte或short带符号拓展为相应int类型数据。
将boolean和char类型数据零位扩展为相应的int类型数据。
对应的数组也会转为int类型字节码指令来处理,大多数类型都是用int类型作为运算类型。
将字节码指令分为9类。
6.4.2 加载和存储指令
加载和存储指令:用于将数据在栈帧中的局部变量表和操作数栈之间来回传输。
- 将一个局部变量加载到操作数栈:iload,iload_,…,aload,aload_。
- 将一个数值从操作数栈存储到局部变量表:istore,istore_,…,astore,astore_。
- 将常量加载到操作数栈:bipush,sipush,…,
6.4.3 运算指令
算术指令用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶。
加减乘除等单词:
Addition,Subtraction,Multiplication,Division,Remainder,Negation,Shifting Left,Shifting Right,Unsign
- 加法指令:iadd,ladd,fadd,dadd
- 减法指令:isub,lsub,fsub,dsub
- 乘法指令:imul,lmul,fmul,dmul
- 除法指令:idiv,ldiv,fidv,ddiv
- 求余指令:irem…
- 取反:ineg…
- 位移:ishl,ishr,iushr,lshl,lshr,lushr
6.4.4 类型转换指令
将两种不同的数值类型相互转换。
小范围往大范围转换。
- int->long,float->double
- long->float,double
- float->double
窄化类型用显式转换指令来完成。
i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l,d2f,过程可能丢失精度。
6.4.5 对象创建与访问指令
类实例和数组都是对象,但创建和操作使用不同字节码指令。
- 创建类实例指令:new
- 创建数组的指令:newarray,anewarray,multianewarray
- 访问类字段,getfield,putfield,getstatic,putstatic
- 数组元素加载到操作数栈的指令:baload,caload,saload…aaload,(ByteArrayLoad)
- 取数组长度的指令:arraylength
- 检查实例类型的指令:instanceof,checkcast
6.4.6 操作数栈管理指令
和操作普通栈操作类似,JVM提供了直接操作操作数站的指令:
- 栈顶1个或2个元素出栈:pop、pop2.
- 复制栈顶一个或两个元素数值并将复制值或双份的复制值重新压入栈顶:dup,dup2,dup_x1,dup2_x1,dup_x2,dup2_x2.
- 将栈最顶端的两个数值互换:swap
6.4.7 控制转移指令
控制指令就是修改PC寄存器的值,使的指向其他指令。
- 条件分支:ifeg,iflt,ifle.ifne,ifgt,ifge,ifnull,ifnonnull等等。
- 复合条件分支:tableswitch,lookupswitch
- 无条件分支:goto,got_w,jsr,jsr_w,ret。
JVM提供的int类型的分支指令最强大,丰富。
6.4.8 方法调用和返回指令
用于方法的调用:
- invokevirtual指令:用于调用对象的实例方法。
- invokeinterface指令:用于调用接口方法,运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用。
- invokespecial指令:调用特殊处理的实例方法,包括实例初始化方法、私有方法和父类方法。
- invokestatic指令:用于调用类静态方法(static方法)。
- invokedynamic指令:用于运行时动态解析出调用点限定符所引用的方法。前四条无法改,这条用户可以设定引导方法。
调用指令与数据类型无关,返回值指令时根据返回值的类型区分的,包括:ireturn(boolean,byte,char,short,int使用),lreturn,freturn,dreturn,areturn,还有return供void的方法、实例初始化方法、类和接口的类初始化方法使用。
6.4.9 异常处理指令
athrow指令来实现,整体采用异常表来完成。
6.4.10 同步指令
JVM可以支持方法级的同步和方法内部一段指令序列的同步。
使用管程来实现(Monitor,更常见的是称为“锁”)来实现。
方法级同步是隐式的,无须通过指令来控制,JVM可以通过常量池中的方法表结构中的ACC_SYNCHRONIZED访问标志得知一个方法是否被声明为同步方法。
同步一段指令集序列通过Java中的synchronized语句来表示,指令集中有monitorenter和monitorexit两条指令来支持。
monitorenter指令和monitorexit指令都是成对出现的。
6.5 公有设计,私有实现
遵循《Java虚拟机规范》是共有设计。
但更希望在约束下对具体实现做出修改和优化的私有实现更鼓励。
虚拟机实现的方式主要有以下两种:
- 将输入的Java虚拟机代码在加载时或执行时翻译成另一种虚拟机的指令集。
- 将输入的Java虚拟机代码在加载时或执行时翻译成宿主机处理程序的本地指令集(即时编译器代码生成技术)。
6.6 Class文件结构的发展
《Java虚拟机规范》已经超过二十年,Java技术体系翻天覆地,但Class文件结构一直处于相对稳定的状态,主体结构,字节码指令和数量几乎没有出现过变动,所有的改建,都集中在访问标志、属性表这些可拓展的数据结构。
访问标志新加入ACC_SYNTHETIC,ACC_ANNOTATION,ACC_ENUM,ACC_BRIDGE,ACC_VARARGS。
属性表增加了20项属性,枚举、变长参数、泛型、动态注解等.
相关文章:
第6章 类文件结构《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》
第6章 类文件结构 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步。 6.1 概述 老师说过,计算机只认识0和1,所以我们写的程序需要被编译器翻译成由0和1构成的二进制格式才能被计算机…...
【Vue】模板语法与指令
个人主页:Guiat 归属专栏:Vue 文章目录 1. Vue 模板语法基础1.1 文本插值1.2 原始 HTML1.3 属性绑定 2. Vue 指令系统2.1 条件渲染2.2 列表渲染2.3 事件处理2.4 表单输入绑定 3. 计算属性与侦听器3.1 计算属性3.2 侦听器 4. 类与样式绑定4.1 绑定 HTML 类…...
Python语法系列博客 · 第5期[特殊字符] 模块与包的导入:构建更大的程序结构
上一期小练习解答(第4期回顾) ✅ 练习1:判断偶数函数 def is_even(num):return num % 2 0print(is_even(4)) # True print(is_even(5)) # False✅ 练习2:求平均值 def avg(*scores):return sum(scores) / len(scores)print(…...
HashMap 初步理解 put 操作流程 HashMap 的线程安全问题
一、HashMap 核心原理 HashMap 是 Java 中最常用的哈希表实现,基于 数组 链表/红黑树 的复合结构,核心特性如下: 哈希函数 键的哈希值通过 hashCode() 计算,并通过扰动函数优化分布:static final int hash(Object ke…...
服务治理-服务发现和负载均衡
第一步:引入依赖 第二步:配置地址 改写购物车服务的代码 负载均衡成功实现。 假如有一个服务挂了,比如说8081,cart-service能不能正常访问,感知到。 再重新启动8081端口。 不管服务宕机也好,还是服务刚启动…...
GNU,GDB,GCC,G++是什么?与其他编译器又有什么关系?
文章目录 前言1. GNU和他的工具1.1 gcc与g1.2 gdb 2.Windows的Mingw/MSVC3.LLVM的clang/clang4.Make/CMake 前言 在开始之前我们先放一段Hello World:hello.c #include <stdio.h>int main() {printf("Hello World");return 0; }然后就是一段老生常…...
定制一款国密浏览器(9):SM4 对称加密算法
上一章介绍了 SM3 算法的移植要点,本章介绍对称加密算法 SM4 的移植要点。 SM4 算法相对 SM3 算法来说复杂一些,但还是比较简单的算法,详细算法说明参考《GMT 0002-2012 SM4分组密码算法》这份文档。铜锁开源项目的实现代码在 sm4.c 文件中,直接拿过来编译就可以。 但需要…...
kafka集群认证
1、安装Kerberos(10.10.10.168) yum install krb5-server krb5-workstation krb5-libs -y 查看版本 klist -V Kerberos 5 version 1.20.1 编辑/etc/hosts 10.10.10.168 ms1 10.10.10.150 ms2 10.10.10.110 ms3 vim /etc/krb5.conf # Configuration snippets ma…...
Mermaid 是什么,为什么适合AI模型和markdown
什么是 Mermaid? Mermaid 是一个基于 JavaScript 的开源绘图和图表工具,允许用户通过简单的文本语法创建图表。它支持生成流程图、时序图、类图、甘特图等多种类型的可视化内容,并直接从类似 Markdown 的代码中渲染。Mermaid 因其与 Markdow…...
为什么信号完整性对于高速连接器设计至关重要?
外部连接器通过在各种电子元件和系统之间可靠地传输数据而不损失保真度来保持信号完整性。在本文中,我们将讨论信号完整性的重要性,回顾高速部署挑战,并重点介绍各种连接器设计策略,以防止失真和降级。 了解连接器信号完整性挑战…...
【FFmpeg从入门到精通】第三章-FFmpeg转封装
1 音视频文件转MP4格式 在互联网常见的格式中,跨平台最好的应该是MP4文件,因为MP4文件既可以在PC平台的 Flashplayer 中播放,又可以在移动平台的 Android、ios 等平台中进行播放,而且使用系统默认的播放器即可播放,因…...
PG数据库推进医疗AI向量搜索优化路径研究(2025年3月修订版)
PG数据库推进医疗AI向量搜索优化路径研究 一、医疗 AI 向量搜索的发展现状与挑战 1.1 医疗数据特征与检索需求 医疗数据作为推动医疗领域进步与创新的关键要素,具有鲜明且复杂的特征。从多模态角度看,医疗数据涵盖了结构化数据,如患者基本信息、检验检查报告中的数值结果;…...
Android 下拉栏中的禁用摄像头和麦克风隐藏
Android 下拉栏中的禁用摄像头和麦克风隐藏 文章目录 Android 下拉栏中的禁用摄像头和麦克风隐藏一、前言二、下拉框中的禁用摄像头和麦克风隐藏实现1、设置支持属性为false2、修改代码 三、其他1、下拉栏中的禁用摄像头和麦克风隐藏小结2、 Android SensorPrivacyService ps&a…...
阿里云Clickhouse 冷热数据分层存储 实战记录
一、 背景 某业务Clickhouse库月数据增长超过2.5T,云上Clickhouse容量并不是无限的,单节点有32T上限,而业务已使用一半以上,依此速度,半年内就将达到上限。 与业务讨论,大致有以下几种解决思路:…...
ARINC818-实现
1.编码和解码;分隔符插入和删除;空闲idle字符插入 2.视频TX和RX接口:可以设计为流传输和帧同步传输 3.传输媒介:光纤或者铜缆 4.链路支持fc 1x,2x,3x,5x,6x,8x 上图中N有限制,N不能允许ADVB帧负载和填充长度不超过2112…...
OpenStack Yoga版安装笔记(23)Swift安装
一、官方文档 Object Storage Install Guide — Swift 2.29.3.dev5 documentation 二、环境准备 之前的实验,已经有controller, compute1, block1节点,并已经完成Keystone、Glance、Nova、Neutron、Cinder等主要OpenStack Service的安装。 此处新增…...
MySql 三大日志(redolog、undolog、binlog)详解
:费解的开关
审题: 本题需要我们将多组测试用例中拉灯数小于等于6的最小拉灯数输出,若拉灯数最小值仍大于6,则输出-1 思路: 方法一:二进制枚举 首先我们先分析一下基本特性: 1.所有的灯不可能重复拉:若拉的数…...
2025.04.19-阿里淘天春招算法岗笔试-第三题
📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 数值平衡之道 问题描述 LYA 是一位精通树形数据结构的数学家,她有一棵包含 n n n...
单片机毕业设计选题物联网计算机电气电子类
题目一:基于单片机的PM2.5空气质量检测仪器 选 1.用到ADC0832模数转换芯片,数据更加精准。 2.使用夏普传感器的GP2Y1010AUOF粉尘传感器实时检测空气中的PM2.5值并通过1602显示出来,检测准确。 3.LCD1602液晶第一行 前面显示测到的PM2.5…...
TDOA解算——牛顿迭代法|以4个基站的三维空间下TDOA定位为背景,使用牛顿迭代法解算。附完整代码,订阅专栏后可复制粘贴
本问所介绍的代码通过TDOA(到达时间差)方法,结合牛顿迭代算法,实现了三维空间内目标位置的定位。系统包含1个主锚点和3个副锚点,通过测量信号到达各基站的时间差计算距离差,最终迭代求解目标坐标。订阅专栏后可以获得完整的MATLAB代码,粘贴到空脚本中即可运行 文章目录 …...
海量聊天数据处理:基于Spring Boot与SharingJDBC的分库分表策略及ClickHouse冷热数据分离
引言 随着互联网应用的快速发展,每天产生的聊天记录数量级已经达到了惊人的程度。以2000万条/天为例,一年下来就是大约7.3亿条记录。如此庞大的数据量给数据库的设计和管理带来了前所未有的挑战。本文将探讨如何使用SharingJDBC整合Spring Boot技术来实…...
网络开发基础(游戏)之 Socket API
Socket简介 Socket (套接字)是网络编程的基础,在 C# 中通过 System.Net.Sockets 命名空间提供了一套完整的 API 来实现网络通信。 网络上的两个程序通过一个双向的通信连接实现数据交换, 这个连接的一端称为一个Socket。 一个Socket包含了进行网络通信必…...
在 Amazon Graviton 上运行大语言模型:CPU 推理性能实测与调优指南
引言 在生成式 AI 浪潮中,GPU 常被视为大模型推理的唯一选择。然而,随着 ARM 架构的崛起和量化技术的成熟,CPU 推理的性价比逐渐凸显。本文基于 Amazon Graviton 系列实例与 llama.cpp 工具链,实测了 Llama 3、DeepSeek 等模型的…...
基于尚硅谷FreeRTOS视频笔记——15—系统配制文件说明与数据规范
目录 配置函数 INCLUDE函数 config函数 数据类型 命名规范 函数与宏 配置函数 官网上可以查找 最核心的就是 config和INCLUDE INCLUDE函数 这些就是裁剪的函数 它们使用一个ifndef。如果定义了,就如果定义了这个宏定义,那么代码就生效。 通过ifn…...
Nacos 使用了什么日志框架?如何配置和查看日志?
Nacos 使用的日志框架 Nacos 主要使用 SLF4j (Simple Logging Facade for Java) 作为日志门面(API),并选择 Logback 作为其底层的日志实现。 SLF4j: 这是一个日志抽象层,允许开发者在代码中使用统一的接口进行日志记录ÿ…...
【基于Fluent+Python耦合的热管理数字孪生系统开发:新能源产品开发的硬核技术实践】
引言:热管理数字孪生的技术革命 在新能源领域(如动力电池、储能系统、光伏逆变器等),热管理是决定产品性能与安全的核心问题。传统热设计依赖实验与仿真割裂的流程,而数字孪生技术通过实时数据驱动与动态建模…...
【工具变量】A股上市公司信息披露质量KV指数测算数据集(含do代码 1991-2024年)
KV指数(Key Value Index)作为评估信息披露质量的关键指标,在证券市场,尤其是A股市场上市公司信息披露监管与评估中占据重要地位。该指数通过系统化、定量化的方法,对企业发布的信息进行全面剖析与打分,精准…...
【ELF2学习板】利用OpenMP采用多核并行技术提升FFTW的性能
目录 引言 OpenMP简介 编译OpenMP支持的FFTW库 部署与测试 测试程序 程序部署 测试结果 结语 引言 在前面已经介绍了在ELF2开发板上运行FFTW计算FFT。今天尝试利用RK3588的多核运算能力来加速FFT运算。FFTW利用多核能力可以考虑使用多线程或者OpenMP。今天介绍一下Ope…...
打靶日记 zico2: 1
一、探测靶机IP(进行信息收集) 主机发现 arp-scan -lnmap -sS -sV -T5 -p- 192.168.10.20 -A二、进行目录枚举 发现dbadmin目录下有个test_db.php 进入后发现是一个登录界面,尝试弱口令,结果是admin,一试就出 得到加…...
【技术派后端篇】 Redis 实现用户活跃度排行榜
在各类互联网应用中,排行榜是一个常见的功能需求,它能够直观地展示用户的表现或贡献情况,提升用户的参与感和竞争意识。在技术派项目中,也引入了用户活跃度排行榜,该排行榜主要基于 Redis 的 ZSET 数据结构来实现。接下…...
MySql Innodb详细解读
参考文档:https://www.cnblogs.com/acatsmiling/p/18424729 一、数据存储:从磁盘到内存的"黑帮走私" 1. 物理结构:表空间与页的江湖规矩 表空间(Tablespace): 所有InnoDB数据存在表空间里&…...
每日两道leetcode
399. 除法求值 - 力扣(LeetCode) 题目 给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。 …...
在RK3588上使用哪个流媒体服务器合适
在RK3588平台上选择合适的流媒体服务器时,需考虑其ARM Cortex-A76/A55架构、硬件编解码能力(如支持H.264/H.265/AV1解码)以及Linux/Android系统支持。以下是推荐的方案: 1. 轻量级方案:GStreamer RTSP 适用场景&…...
分享一个DeepSeek+自建知识库实现人工智能,智能回答高级用法。
这个是我自己搞的DeepSeek大模型自建知识库相结合到一起实现了更强大的回答问题能力还有智能资源推荐等功能。如果感兴趣的小伙伴可以联系进行聊聊,这个成品已经有了实现了,所以可以融入到你的项目,或者毕设什么的还可以去参加比赛等等。 1.项…...
PyTorch 深度学习实战(38):注意力机制全面解析(从Seq2Seq到Transformer)
在上一篇文章中,我们探讨了分布式训练实战。本文将深入解析注意力机制的完整发展历程,从最初的Seq2Seq模型到革命性的Transformer架构。我们将使用PyTorch实现2个关键阶段的注意力机制变体,并在机器翻译任务上进行对比实验。 一、注意力机制演…...
Android Studio 获取配置资源与第三方包信息详解
文章目录 Android Studio 获取配置资源与第三方包信息详解一、获取资源文件中的配置1. 获取颜色值Java 中获取:Kotlin 中获取: 2. 获取字符串Java 中获取:Kotlin 中获取: 3. 获取尺寸值Java 中获取:Kotlin 中获取&…...
【网络初识】从零开始彻底了解网络编程(一)
本篇博客给大家带来的是网络的知识点. 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅🚀 要开心要快乐顺便进步 一. 网络…...
Vivado比特流生成、下载及板级验证操作步骤
1. 前期准备 安装Vivado软件:确保Vivado开发环境已正确安装并配置。创建工程: 打开Vivado,点击“Create Project”新建工程。设置工程名称(例如“led_flow”)和路径。选择目标FPGA型号(例如XC7A35TFFG484&…...
【Flutter DevTools】性能优化的瑞士军刀
一、性能分析:帧率与资源监控 1.1 帧率监控(Performance面板) 通过Performance面板可实时捕获应用的渲染流水线数据。开发者点击"Record"按钮后,DevTools会以时间轴形式展示每一帧的构建、布局、绘制耗时。当帧率低于…...
使用Redis实现实时排行榜
为了实现一个实时排行榜系统,我们可以使用Redis的有序集合(ZSet),其底层通常是使用跳跃表实现的。有序集合允许我们按照分数(score)对成员(member)进行排序,因此非常适合…...
HTML5 应用程序缓存:原理、实践与演进
在 Web 技术的发展历程中,HTML5 引入的应用程序缓存(Application Cache)曾是提升 Web 应用离线体验的重要技术。它允许 Web 应用进行缓存,使用户在没有因特网连接时也能访问应用,为 Web 应用带来了显著的优势。然而&am…...
Compose笔记(十七)--AsyncImage
这一节了解一下Compose中的AsyncImage的使用,AsyncImage是由 Coil库提供的一个用于异步加载图片的组件。它支持加载网络图片、本地图片资源,并提供了占位符、错误处理、过渡动画等功能,简单介绍如下: API 1. model 含义:指定要加…...
Python语法系列博客 · 第7期[特殊字符] 列表推导式与字典推导式:更优雅地处理数据结构
上一期小练习解答(第6期回顾) ✅ 练习1:统计文件行数 with open("data.txt", "r", encoding"utf-8") as f:lines f.readlines()print(f"总行数:{len(lines)}")✅ 练习2:反…...
Redis--主从复制
目录 一、配置 1.1 建立复制 1.2 断开复制 1.3 安全性 1.4 只读 1.5 传输延迟 二、拓扑 2.1 一主一从结构 2.2 一主多从结构 2.3 树形主从结构 在分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他服务器,满足故障恢 复和负载均衡等需求…...
FPGA练习———DDS波形发生器
简介:使用DDS波形发生器可以在fpga上生成方波、正弦波等波形,其具体方法是计算相位的变化,然后根据数据表的数值进行数模转化改变波形。 DDS的第一步是生成一个相位加法器 相位加法器 在生成一个波,例如正弦波时,我们…...
力扣面试150题-- 存在重复元素 II和最长连续序列
Day 26 题目描述 思路 定义一个map用来存放每个元素以及它对应的序号从前向后遍历数组如果该元素存在于map(说明满足了重复元素的条件),用当前元素的序号值减去map中存放的序号值(因为是从前遍历的所以当前元素序号一定大于存放…...
卸载Anaconda并保留虚拟环境,重装Anaconda并还原之前的虚拟环境
参考 https://blog.csdn.net/qq_63611690/article/details/134560333 该博文是虚拟环境和Anaconda安装路径在一起 我的是虚拟环境早就搞到了别的盘 问题描述 我之前把Anaconda安装到了C盘,随之时间推移,C盘占用空间越来越大。我想把Anaconda卸载重装…...
ArcGIS及其组件抛出 -- “Sorry, this application cannot run under a Virtual Machine.“
产生背景: 使用的是“破解版本”或“被套壳过”的非官方 ArcGIS 版本 破解版本作者为了防止: 被研究破解方式 被自动化抓包/提权/逆向 被企业环境中部署多机使用 通常会加入**“虚拟化环境检测阻断运行”机制** 原因解释: 说明你当前运…...
Ubuntu 25.04 “Plucky Puffin” 正式发布
Ubuntu 25.04 “Plucky Puffin” 于 2025 年 4 月 17 日正式发布。这是一个短期支持版本,只支持到 2026 年 1 月1。以下是该版本的一些主要新变化: 内核与系统:采用 Linux 6.14 内核;systemd v257.4 带来重要上游更新,…...