JVM—Class类文件结构详解

news2025/1/18 18:45:09

Class类文件的结构

要了解Class文件的结构首先得了解Class文件所采用的数据类型:
Class文件格式采用一种类似C语言结构体的伪结构来存储数据,这种伪结构只有两种数据结构,即无符号数,解析Class文件全是以这两个数据结构为基础。

  • 无符号数:属于基本的数据类型,由1字节、2字节、4字节、8字节分别用u1、u2、u3、u8表示,可以用来描述数字、索引引用、数量值或者UTF-8编码构成字符串值。
  • :是由多个无符号数或者表构成的复合数据结构,习惯以"_info"结尾Class文件本质也可以看作一张表

Class文件格式

Class文件格式严格按照下表的方式进行排列构成

类型名称数量
u4magic1
u2minor_version1
u2major_version1
u2constant_pool_count1
cp_infoconstant_poolconstant_pool_count -1
u2access_flags1
u2this_class1
u2super_class1
u2interface_count1
u2interfacesinterface_count
u2fields_count1
field_infofieldsfields_count
u2methods_count1
method_infomethodsmethods_count
u2attributes_count1
attribute_infoattributesattributes_count

下面我们用一个实际编译的class文作为例子来分析class类文件的结构:所有的文件机构类型基于下面的class文件进行分析。
java源代码

public class Test {
    private int m;
    public int inc(){
        return m + 1;
    }
}

编译后的class文件

cafe babe 0000 0034 0013 0a00 0400 0f09
0003 0010 0700 1107 0012 0100 016d 0100
0149 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 0369 6e63
0100 0328 2949 0100 0a53 6f75 7263 6546
696c 6501 0009 5465 7374 2e6a 6176 610c
0007 0008 0c00 0500 0601 0004 5465 7374
0100 106a 6176 612f 6c61 6e67 2f4f 626a
6563 7400 2100 0300 0400 0000 0100 0200
0500 0600 0000 0200 0100 0700 0800 0100
0900 0000 1d00 0100 0100 0000 052a b700
01b1 0000 0001 000a 0000 0006 0001 0000
0001 0001 000b 000c 0001 0009 0000 001f
0002 0001 0000 0007 2ab4 0002 0460 ac00
0000 0100 0a00 0000 0600 0100 0000 0400
0100 0d00 0000 0200 0e

1.魔数与class文件的版本

ca fe ba be //魔数值0xCAFEBABE

上述代码可以看出class文件的魔术值为0xCAFEBABE。

MagicNumber为每个Class文件的头4个字节,唯一作用就是用于判断这个文件是否为一个能被虚拟机接受的Class文件,为什么使用魔数不使用拓展名进行判断?(出于安全考虑,拓展名可以随意修改,魔术值只要没有被广泛采用就不会引起混淆)

00 00 00 34 //前两位为次版本号 后两位为主版本号

版本号为魔数后4个字节前两个字节问次版本号,后两个字节为主版本号,0034十进制表示52为java8,关于次版本号,在jdk1.2时短暂使用过,从1.2到jdk12之前次版本号均为零,未被使用过。

2.常量池

在版本号之后,则是常量池入口,常量池在class中的作用非常重要,就是class文件中的资源仓库,通常也是占用class文件空间最大的数据项目之一。
由于常量池长度不是一定的,所以在常量池的入口处需要放置一个两个字节的数据来记录常量池的容量由多大,下面例子中的字节码就表示常量池的容量为大小为18。

00 13       //00 13表示常量中常量的数量为18 

常量池的每一项都是一个表,表结构起始的第一位为一个一字节的tag标志位来表示当前常量属于哪一类常量类型,截至jdk13,常量表中分别由17中不同类型的常量,且17种常量类型各自由着完全独立的数据结构,只能逐项进行讲解。

类型标志描述
CONSTANT_Utf8_info1UTF-8编码的字符串
CONSTANT_Integer_info3整型字面量
CONSTANT_Float_info4浮点型字面量
CONSTANT_Long_info5长整型字面量
CONSTANT_Double_info6双精度浮点型字面量
CONSTANT_Class_info7类或接口的符号引用
CONSTANT_String_info8字符串类型字面量
CONSTANT_Fieldref_info9字段的符号引用
CONSTANT_Methodref_info10类中方法的符号引用
CONSTANT_InterfaceMethodref_info11接口中方法的符号引用
CONSTANT_NameAndType_info12字段或方法的部分符号引用
CONSTANT_MethodType_info15表示方法句柄
CONSTANT_MethodHandle_info16表示方法类型
CONSTANT_Dynamic_info17表示一个动态计算常量
CONSTANT_InvokeDynamic_info18表示一个动态方法调用点
CONSTANT_Module_info19表示一个模块
CONSTANT_Package_info20表示一个模块中开放或者导出的包

2.1常量池中第1个常量

观察例子中常量池第一个常量,它的标志位为0x0a,查上表可得这个常量类型CONSTANT_Methoddref_info 类型,CONSTANT_Methoddref_info 类型结构为

类型名称数量描述
u1tag1值为10
u2index1指向方法的类描述符CONSTANT_Class_info索引项
u2index1指向名称及类型描述符CONTANT_Name_AndType索引项

结合字节码分析,该类型一共占5个字节。
第一个占1个字节,用于区分索引类型,
第二个占2个字节,用于指向该类型中的CONSTANT_Class_info在常量池中的索引
第三个占2个字节,用于指向该类型中的CONSTANT_NameAndType在常量池中的索引

0a			//0a表示第 1 个常量类型为CONSTANT_Methoddref_info 长度为5个字节(包含标志位)
00 04       //表示声明方法的类的字段 CONSTANT_Class_info的索引项在常量池第4项常量 
00 0f       //表示名称及类型字段 CONSTANT_NameAndType的索引项在常量池的第 15 项常量

2.2常量池中第2个常量

例子中常量池第二个常量,它的标志位为0x09,查上表可得常量类型CONSTANT_Fieldref_info类型结构为

类型名称数量描述
u1tag1值为9
u2index1指向方法的类描述符CONSTANT_Class_info索引项
u2index1指向名称及类型描述符CONTANT_Name_AndType索引项

结合字节码分析,该类型一共占5个字节。
第一个占1个字节,用于区分索引类型,
第二个占2个字节,用于指向该类型中的CONSTANT_Class_info在常量池中的索引
第三个占2个字节,用于指向该类型中的CONSTANT_NameAndType在常量池中的索引

09			//表示第 2 个常量类型为 CONSTANT_Fieldref_info 长度为5个字节(包含标志位)
00 03 		//表示声明方法的类的字段 CONSTANT_Class_info 的索引项在常量池第 3 项常量 
00 10 		//表示字段CONSTANT_Name-AndType的索引在常量池的第 16 项

2.3常量池中第3~4常量

例子中第3和第4个两个常量类型一样,它的标志位都为0x07,查上表可得常量类型**CONTANT_Class_info **类型结构为

类型名称数量描述
u1tag1值为7
u2index1指向全限定名常量的索引

结合字节码分析,该类型一共占3个字节
第一个占1个字节,用于区分索引类型
第二个占2个字节,用于指向全限定名常量项的索引

07			//表示第 3 个常量类型为 CONTANT_Class_info 长度为 3 个字节(包含标志位)
00 11       //表示全限定名存在常量池的第 17 项常量
07    		//表示第 4 个常量类型为 CONTANT_Class_info 长度为 3 个字节(包含标志位)
00 12 		//表示全限定名存在常量池的第 18 项常量

2.4 常量池中5~14及17,18常量

5到14以及17,18常量,它们标志位都是0x01,查上标可得常量类型为CONTANT_Utf8_info 类型结构为
**CONTANT_Class_info **类型结构为

类型名称数量描述
u1tag1值为1
u2length1UTF-8编码的字符串占用了字节数
u1byteslength长度为length的UTF-8编码的字符串
结合字节码分析
第一个占1个字节,用于区分索引类型
第二个占2个字节,用于描述该常量占用多少(length)字节数
第三个占length个字节数,用于存储utf-8编码的字符串
01 			//表示第 5 个常量类型为 CONTANT_Utf8_info 长度为 4 个字节(包含标志位)
00 01 		//表示utf-8编码占用了字节数为 1
6d    		//6d 十进制为109 utf-8对应 m
01			//表示第 6 个常量类型为 CONTANT_Utf8_info
00 01 		//表示长度为 1
49 			//49 十进制为 73 utf8对应 I
01			//第 7 个常量为CONTANT_Utf8_info
00 06		//常量长度为 6
3c 69 6e 69 74 3e // 一一对应 '<init>'
<!-- 下面utf全部简略的描述 -->
01 			//第 8 个常量
00 03 		//长度为 3
28 29 56	//utf对应 ()V
01 			//第 9 个常量
00 04 		//长度为 4
43 6f 64 65 // Code
01 			//第 10 个变量
00 0f		//长度为 15
4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 //LineNumberTable
01 			//第 11 个变量
00 03		//长度为3
69 6e 63	//inc
01			//第 12 个变量
00 03		//长度为3
28 29 49	//()I
01  		//第 13 个变量
00 0a		//长度为10
53 6f 75 72 63 65 46 69 6c 65  //SourceFile
01 			//第 14 个变量
00 09 		//长度为9
54 65 73 74 2e 6a 61 76 61 //Test.java
······
01 			//第 17 个常量为 utf-8
00 04		//长度为 4
54 65 73 74 //Test
01			//第 18 个常量为 utf-8
00 10		//长度为 16
6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74  //java/lang/Object

2.5常量池15,16常量

15,16常量,它们的标志为都是0x0c查上表可得常量类型**CONSTANT_NameAndType_info **类型结构为

类型名称数量描述
u1tag1值为12
u2index1指向该字段或方法名称常量项索引
u2index1指向指向该字段或方法描述常量项索引

结合字节码分析,该类型一共占5个字节
第一个占1个字节,用于区分索引类型
第二个占2个字节,指向该字段或方法名称常量项索引
第三个占2个字节,指向指向该字段或方法描述常量项索引

0c 			//表示第 15 个常量量类型为 CONSTANT_NameAndType_info 长度为5个字节(包含标志位)
00 07 		//表示该字段的表示的字段或方法的名称为常量池的第7个常量
00 08 		//表示该字段表示的字段或方法的描述为位常量池的第8个常量
0c			//表示第 16 个常量量类型为 CONSTANT_NameAndType_info 长度为5个字节(包含标志位)
00 05		//表示该字段的表示的字段或方法的名称为常量池的第5个常量
00 06		//表示该字段表示的字段或方法的描述为位常量池的第6个常量

到这常量池已经全部解析完成: 可以使用javap命令输出常量表,对常量表进行验证:

javap -verbose Test

输出结果
!](https://img-blog.csdnimg.cn/e293555d7ddf46d08d4910b399f1529d.png)

访问标志(access_flag)

在常量池结束后,由两个2字节的访问标志,在这里标识的是类的一些基本类型以及属性如访问修饰,是否final是否abstract。
具体的访问标志位以及标志的含义有

标志名称标志值含义
ACC_PUBLIC0x0001是否为public类型
ACC_FINAL0x0010是否被声明为final,只有类能设置
ACC_SUPER0x0020是否允许使用invokespecial字节码指令的新语义
ACC_INTERFACE0x0200标识这是一个接口
ACC_ABSTRACT0x0400是否为abstract类型,对于接口或者抽象类来说,此标志位为真,其他类型为假
ACC_SYNTHETIC0x1000是否为这个类并非由用户代码产生的
ACC_ANNOTATION0x2000标识这是一个注解
ACC_ENUM0x4000标识这是一个枚举类
ACC_MODULE0x8000标识这是一个模块

查看字节码,access_flag占用两个字节。
0021查上表可得该类使用invokespecial字节码指令的新语义,且被public修饰

00 21		//access_flags 标志位占用 2个字节位,0021表示被public修饰符修饰,且使用invokespecial字节码指令的新语义

类索引、父类索引与接口索引集合

类索引和父类索引都是一个两个字节的数据,而接口索引是一组两字节的数据集合,Class文件中由这三项数据来确定该类型的继承关系,类索引用于确定该类的全限类名,父类索引用于确定该类父类的全限类名。由于java语言特性不支持多类继承,所以父类索引只有一个,接口索引集合用于描述这类实现了哪些接口。
根据字节码进行分析:

00 03 		//this_class 类索引,占用 2 个字节,表示在类名称存放在常量池第 3 项常量中
00 04 		//super_class 父类索引,占用 2 个字节,表示父类名称存放在常量池第 4 项常量中
00 			//interface_count 占用 1 个字节,表示实现接口的数量为0
00			//interfaces 接口为空

字段表集合(field_info)

字段表用于描述接口或者类中声明的变量中包含哪些信息。包括类级变量和实例级变量,但不包括在方法内部声明局部变量。
字段表的格式

类型名称数量
u2access_flags1
u2name_index1
u2descriptor_index1
u2attribute_count1
attribute_infoattributesattribute_count

字段修饰符,放在access_flag中,占用2个字节,与类中的access类似,标志位和含义如下表所示

标志名称标志值含义
ACC_PUBLIC0x0001字段是否public
ACC_PRIVATE0x0002字段是否private
ACC_PROTECTED0x0004字段是否protected
ACC_STATIC0x0008字段是否static
ACC_FINAL0x0010字段是否final
ACC_VOLATELE0x0040字段是否volatile
ACC_TRANSIENT0x0080字段是否transient
ACC_SYNTHETIC0x1000字段是否由编译器自动产生
ACC_ENUM0x4000字段是否enum

access_flag标志之后是两项索引值:name_index和descriptor_index,都是对常量池项的引用,分别表示字段简单名称和字段或方法的描述符

<!-- 字段表集合 -->
00 01 		//fields_count 表示只有 1 个字段表数据 占用 2 个字节
00 02		//access_flags 表示字段修饰符为private 占用 2 个字节
00 05 		//name_index 表示字段名称存放在常量池第 5 项常量 占用 2 个字节
00 06		//descriptor_index 表示字段方法的描述存放在常量池的第 6 项常量 占用 2 个字节
00 			//attributes_count 属性表数量为0 占用 2 个字节
00 			//attributes 表示属性表集合为空

方法表集合(method_info)

方法表集合与字段表集合类似,对字段和方法的描述几乎一致,方法表的结构和字段表几乎一致,仅仅是access_flag的访问标志的类型不同。
方法表的结构如下

类型名称数量
u2access_flags1
u2name_index1
u2descriptor_index1
u2attribute_count1
attribute_infoattributesattribute_count

方法表集合首先有method_count表示方法表集合中包含几个方法表
字节码如下

<!-- 方法表集合 -->
00 02 		//methods_count 表示表示方法表集合中包含 2 个方法

方法访问标志类型如下

标志名称标志值含义
ACC_PUBLIC0x0001方法是否public
ACC_PRIVATE0x0002方法是否private
ACC_PROTECTED0x0004方法是否protected
ACC_STATIC0x0008方法是否static
ACC_FINAL0x0010方法是否final
ACC_SYNCHRONIZED0x0020方法是否synchronized
ACC_BRIDGE0x0040方法是否是编译器产生的桥接方法
ACC_VARARGS0x0080方法是否接受不定参数
ACC_NATIVE0x0100方法是否为native
ACC_ABSTRACT0x0400方法是否为abstract
ACC_SYNTHETIC0x1000方法是否由编译器自动产生

方法的定义通过访问索引、名称索引、描述索引进行描述,而方法内的代码通过javac编译存到了方法属性表中Code属性中,Code是class文最具拓展性的一部分。
下面将对两个方法表分别进行分析

第一个方法表

<!-- 第一个方法表 -->
00 01 		//access_flags 表示方法修饰符为public 占用 2 个字节
00 07		//name_index 方法名称存放在常量池第 7 个 占用 2 个字节
00 08		//descriptor_index 表示方法描述存放在常量池第 8 个 占用 2 个字节
00 01		//attributes_count 表示此方法属性表集合中有 1 项属性 占用 2 个字节
<!-- attribute_info (code)-->
00 09		//attribute_name_index 表示属性存放在常量池第 9 项 占用 2 个字节
00 00 00 1d //attribute_lenth 表示该属性的长度 占用 4 个字节
00 01  		//max_stack 操作数栈的最大深度 占用 2 个字节
00 01 		//max_locals 局部变量表所需的存储空间 占用两个字节
00 00 00 05 //code_length 表示字节码长度,占用 4 个字节
2a b7 00 01 b1 //code 用于存储编译后的字节码指令 占用code_length 个字节

00 00 		//exception_table_length 异常表长度 占用 2 个字节

00 01 		//code属性中的 attributes_count 占用两个字节
00 0a 		//attribute_name_index 属性名称在常量池的第10项常量
00 00 00 06 //LineNumber类型的 attribute_length 属性长度 占用 4 个字节
00 01 		//line_number_table_length 表示有几个line_number_info类型的数据 占用 2 个字节
<!-- line_number_info -->
00 00 		//start_pc 字节码行号
00 01 		//line_number java源码行号

第二个方法表

<!-- 第二个方法表 -->
00 01 		//access_flags 表示方法修饰符为public 占用 2 个字节
00 0b 		//name_index 方法名称存放在常量池第 11 个 占用 2 个字节
00 0c 		//descriptor_index 表示方法描述存放在常量池第 12 个 占用 2 个字节
00 01 		//attributes_count 表示此方法属性表集合中有 1 项属性 占用 2 个字节
<!-- attribute_info (code) -->
00 09 		//attribute_name_index 表示属性存放在常量池第 9 项 占用 2 个字节
00 00 00 1f //attribute_lenth 表示该属性的长度 占用 4 个字节
00 02		//max_stack 操作数栈的最大深度 占用 2 个字节
00 01 		//max_locals 局部变量表所需的存储空间 占用 2 个字节
00 00 00 07 //code_length 表示字节码的长度 占用 4 个字节
2a b4 00 02 04 60 ac// code 用于存储编译后的字节码指令 占用code_length个字节
00 00 		//exception_table_length 异常表长度 占用 2 个字节
00 01 		//cod属性中的 attributes_count 表示有几个属性 占用两个字节
00 0a 		//attribute_name_index 属性名在常量池中的索引 表示是常量池中第 10 个索引 占用 2 个字节
00 00 00 06 //LineNumber类型的 attribute_length 属性长度占用 4 个字节
00 01 		//line_number_table_length 表示有几个 line_number_info类型的数据 站哟 两个字节
<!-- line_number_info -->
00 00 		//start_pc 字节码行号
00 04 		//line_number java源码行号

属性表集合

属性表在之前的讲解方法表的讲解已经出现过了,不同类型属性表的结构都不同,在这里就不细说了,就介绍一下,前面出现的Code属性表和class文件最后的属性表结构。

Code属性表

Code属性表的结构

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2max_stack1
u2max_locals1
u1code_length1
u2codecode_length
u2exception_table_length1
exception_infoexception_tableexception_table_length
u2attributes_count1
attribute_infobattributesattribute_count

attribute_name_index是指向CONSTANT_Utf8_info型常量的索引,此常量固定为“Code”,代表该属性的属性名称,attribute_length表示属性长度,max_stack表示操作数栈深度的最大值,max_locals代表局部变量表所需的存储空间,max_locals单位是变量槽(虚拟机为局部变量分配内存所使用的最小单位),code_length和code是用来存储java源文件编译后生成的字节码指令,code_length代表字节码长度,code用于存储字节码指令。exception_length表示异常处理表集合长度,exception_table表示异常处理表集合,异常处理表并不是Code必须部分!

LineNumberTable属性表

LineNumberTable属性用于描述java源码行号与上传字节码行号之间的对应关系,并不是运行的必须属性,但会默认生成到class文件中,主要作用就是抛出异常是会显示行号,以及调试程序时可以根据源码行号进行设置断点。
LineNumberTable的属性结构如下

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2line_number_table_length1
line_number_infoline_number_tableline_number_table_length

line_number_table是一个l类型为line_number_info的集合,包含start_pc和line_number两个属性都是占两个字节,前者是字节码行号,后者是java源码行号。

Code属性表与LineNumberTable属性表字节码分析如下

<!-- 第一个方法 attribute_info (code)-->
00 09		//attribute_name_index 表示属性存放在常量池第 9 项 占用 2 个字节
00 00 00 1d //attribute_lenth 表示该属性的长度 占用 4 个字节
00 01  		//max_stack 操作数栈的最大深度 占用 2 个字节
00 01 		//max_locals 局部变量表所需的存储空间 占用两个字节
00 00 00 05 //code_length 表示字节码长度,占用 4 个字节
2a b7 00 01 b1 //code 用于存储编译后的字节码指令 占用code_length 个字节

00 00 		//exception_table_length 异常表长度 占用 2 个字节

00 01 		//code属性中的 attributes_count 占用两个字节
00 0a 		//attribute_name_index 属性名称在常量池的第10项常量
00 00 00 06 //LineNumber类型的 attribute_length 属性长度 占用 4 个字节
00 01 		//line_number_table_length 表示有几个line_number_info类型的数据 占用 2 个字节
<!-- line_number_info -->
00 00 		//start_pc 字节码行号
00 01 		//line_number java源码行号

<!--第二个方法 attribute_info (code) -->
00 09 		//attribute_name_index 表示属性存放在常量池第 9 项 占用 2 个字节
00 00 00 1f //attribute_lenth 表示该属性的长度 占用 4 个字节
00 02		//max_stack 操作数栈的最大深度 占用 2 个字节
00 01 		//max_locals 局部变量表所需的存储空间 占用 2 个字节
00 00 00 07 //code_length 表示字节码的长度 占用 4 个字节
2a b4 00 02 04 60 ac// code 用于存储编译后的字节码指令 占用code_length个字节
00 00 		//exception_table_length 异常表长度 占用 2 个字节
00 01 		//cod属性中的 attributes_count 表示有几个属性 占用两个字节
00 0a 		//attribute_name_index 属性名在常量池中的索引 表示是常量池中第 10 个索引 占用 2 个字节
00 00 00 06 //LineNumber类型的 attribute_length 属性长度占用 4 个字节
00 01 		//line_number_table_length 表示有几个 line_number_info类型的数据 站哟 两个字节
<!-- line_number_info -->
00 00 		//start_pc 字节码行号
00 04 		//line_number java源码行号

SourceFile属性

SourceFile属性用于记录生成这个Class文件的源码文件名称,当类名和文件名不一致时抛出异常。
这个属性的结构为

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2sourcefile_index1

class文件属性表集合以及SourceFile字节码分析

<!-- 属性表 -->
00 01 		//attributes_count 表示有几个属性 占用两个字符
<!-- attribute_info -->
00 0d 		//attribute_name_index 属性名称在常量池中的索引 占用 2 个字节
00 00 00 02 //attribute_length 属性长度 占用 4 个字节
00 0e		//sourcefile_index 资源文件名称在常量池中的索引

到此为止,class文件全部解析完成,读者也可以使用该java源代码自己进行编译按照该思路进行分析,相信你们一定也会有所收获!

参考书籍:深入理解java虚拟机(第3版)

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

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

相关文章

【数据结构】什么是堆,如何使用无序数组生成一个堆?

文章目录 一、堆的概念及其介绍二、如何使用无序序列构建一个堆&#xff1f;三、C语言实现堆的基本操作结构体创建与销毁获取堆顶数据与个数及堆的判空堆的插入与删除 源代码分享 一、堆的概念及其介绍 堆(Heap)是计算机科学中一类特殊的数据结构的统称&#xff0c;堆通常是一…

LEETCODE 每日一题 1093.大样本统计

题目描述 前往leetcode1093题 我们对 0 到 255 之间的整数进行采样&#xff0c;并将结果存储在数组 count 中&#xff1a;count[k] 就是整数 k 在样本中出现的次数。 计算以下统计数据: minimum &#xff1a;样本中的最小元素。 maximum &#xff1a;样品中的最大元素。 mean &…

【Log】About these two years

文章目录 第一篇博客&#xff1f;成长收获的季节Future 第一篇博客&#xff1f; 第一次在CSDN发布博客&#xff0c;是当初我学习嵌入式的时候&#xff0c;那个时候我们做了一个大创&#xff0c;其中使用到了激光雷达&#xff0c;然后我就负责激光雷达部分代码的编写和设计&…

AI-新手玩转RKNN

关于RKNN RKNN 是Rockchip npu 平台使用的模型类型&#xff0c;以.rknn后缀结尾的模型文件。Rockchip 提供了完整了模型转换 Python 工具&#xff0c;方便用户将自主研发的算法模型转换成 RKNN 模型&#xff0c;同时 Rockchip 也提供了C/C和Python API 接口。 #mermaid-svg-M7l…

电子器件系列37:SD卡座(Push-Push和Push-Pull)

SD卡座是目前最通用的数据存储卡座、记忆卡座。在各种通讯数码产品、安防产品、带储存类产品等设备上都有所应用。有着性价比高、存储容量大、使用便捷、通用性以及安全性强等特点。自弹式SD卡座的卡槽底部会设有一个小直径、小线径的弹簧或一种切口式弹片。当装入SD卡时&#…

Kafka如何保证数据高可靠

这节课给大家分享一下Kafka的数据高可靠。为什么要讲这个&#xff1f;因为Kafka它本身不是一个金融级别数据可靠的分布式消息系统。 虽然说它存储到某个topic里的数据会先拆分多个partition&#xff0c;这体现了分治的一个思想。每一个partition在最终存储的时候会保存多个副本…

117.【微信小程序】

微信小程序 (一)、微信小程序概括1.微信小程序简介(1).小程序与普通网页开发的区别 2.注册微信小程序账号(1).注册小程序账号(2).获取小程序的AppID 3.安装微信开发者工具(1).微信开发者工具的简介:(2).微信开发者工具的下载 4.创建第一个小程序(1).创建小程序步骤(2).开发者工…

域横向移动-传递攻击atschtasks

横向移动就是拿下对方一台主机后&#xff0c;以拿下的那台主机作为跳板&#xff0c;对内网的其他主机再进行后渗透&#xff0c;拿到其他内网主机的权限的过程。叫做横向移动。横向移动的主要目的就是扩大战果。 传递攻击主要建立在明文和hash值获取基础上进行攻击。 at和scht…

Typora改变字体颜色

方法一&#xff1a;下载AutoHotkey并创建快捷键的方法&#xff08;推荐&#xff09; 第一步&#xff1a;在官网&#xff08;https://www.autohotkey.com/&#xff09;下载 AutoHotkey并傻瓜式安装&#xff0c;安装在任意盘符下均可&#xff1b; 第二步&#xff1a;在安装目录…

STM32F4_I2C(从机EEPROM/MPU-6050)协议详解

目录 1. I2C是什么 2. I2C物理层介绍 3. I2C协议层介绍 3.1 I2C基本读写过程 3.1.1 通讯复合格式 3.2 通讯的起始和停止信号 3.3 数据有效性 3.4 地址及数据方向 3.5 响应 4. STM32的I2C特性及架构 4.1 I2C架构剖析 5. I2C通讯过程 5.1 主发送器 5.2 主接收器 6…

Windows文件自动备份——“使用文件历史记录进行备份”

一、背景 因为有一些重要的文件需要经常改动&#xff0c;同时也有“找到某文件某历史版本”的需求&#xff0c;但考虑到时常手动备份比较麻烦&#xff0c;就想到了使用Windows自带的文件备份功能——“使用文件历史记录进行备份”来帮助进行文件的备份和版本管理。 二、环境 1…

一个测试开发人员在字节的7年,太真实了...

测试这条路是坎坷的&#xff0c;我自己深有体会。 我们的起点低&#xff0c;基础差。 测试这个职位也很尴尬&#xff0c;很少有公司会有针对性的对测试人员做成长规划&#xff0c;也很少有公司会那么重视测试人员&#xff0c; 也许进了像 BATJ 这样的大厂会好一点。 但是大多数…

nacos2.2.1搭建

springboot 3.0集成nacos2.2.1内容可评论区Q我 搭建环境&#xff1a; Java版本&#xff1a;11.0.18 系统&#xff1a;window7 数据库&#xff1a;mysql8.0.29 第一步&#xff0c;下载nacos&#xff0c;下载地址&#xff1a; https://github.com/alibaba/nacos/releases/d…

HACKABLE: III实战演练

文章目录 HACKABLE: III实战演练一、前期准备1、相关信息 二、信息收集1、端口扫描2、访问网站3、查看网站源码4、扫描目录5、访问网址6、查看并下载7、访问网站8、查看文件9、解密10、访问网站11、访问网站12、查看文件13、解密14、访问网站15、访问网站16、下载图片17、隐写1…

CrossOver软件好用吗?最新版22.1.1有哪些优势功能

CrossOver2023是一款系统兼容软件 让您可以在Mac和Linux系统上运行Win应用&#xff0c;不必重启系统&#xff0c;不必使用虚拟机。通过CrossOver&#xff0c; 您可以从dock直接启动Wind应用&#xff0c;与您的Mac和Linux系统功能无缝集成。crossover兼容软件是可以在苹果电脑中…

oracle的基本使用(建表,操作表等)

一、表空间&#xff0c;用户 1、创建表空间 使用system登录 创建表空间 waterboss 为表空间名称datafile 用于设置物理文件名称size 用于设置表空间的初始大小autoextend on 用于设置自动增长&#xff0c;如果存储量超过初始大小&#xff0c;则开始自动扩容next 用于设置每次…

tiechui_lesson14_网络连接请求的拦截

这一节主要学习网络请求的过滤&#xff0c;铁锤大佬讲了些关于IRP的知识。 笔记 先祭出一张灵魂作画&#xff0c;这是用来描述IRP的流转形式的。 通过这幅图着重解释了一下IoSkipCurrentIrpStackLocation(pirp);的过程&#xff0c;就是在流转到当前的IRP请求之后&#xff0c…

Jarvis OJ pwn——level1

checksec&& 运行 ida main函数里的vulnerable_function函数存在溢出 给输入分配的栈空间为0x88 利用思路 ret2shellcode 代码 Author : 白银 Date : 2023-05-27 14:43:28 LastEditors : 白银 LastEditTime : 2023-05-27 16:52:19 FilePath : /pw…

五十行代码教你写一个简单的内存池(二级指针的应用)

固定大小内存的内存池实现 该内存池是一个很简单的内存池&#xff0c;只能申请固定大小的内存&#xff0c;仅供学习 要点&#xff1a; 构造隐式链表二级指针 存储结构 typedef struct mempool_s{int block_size; // 每一块的大虚哎int free_count; // 剩余有多少块是可以…

C#医院LIS系统源码 LIS实验室管理信息系统源码 LIS检验系统源码

1、LIS系统技术框架 &#xff08;1&#xff09;总体框架&#xff1a; SaaS架构的Client/Server应用 服务可伸缩&#xff0c;多服务协同 服务可拆分&#xff0c;功能易扩展 &#xff08;2&#xff09;技术细节&#xff1a; 体系结构&#xff1a;Client/Server架构 客户端…