• 平台无关性
    • Class类文件的结构
      • Class的数据类型
        • 无符号数
      • 魔数与Class文件的版本
      • 常量池
        • CONSTANT_Class_info
        • CONSTANT_Utf8_info
        • CONSTANT_Integer_info
        • CONSTANT_Float_info
        • CONSTANT_Long_info
        • CONSTANT_Double_info
        • CONSTANT_String_info
        • CONSTANT_Fieldref_info
        • CONSTANT_Methodref_info
        • CONSTANT_InterfaceMethod-ref_info
        • CONSTANT_NameAndType_info
        • CONSTANT_MethodHandle_info
        • CONSTANT_Module_info
        • CONSTANT_Package_info
      • 访问标志
      • 类索引、父类索引和接口索引集合
      • 字段表集合
        • 字段访问标志
        • 名称与类型常量池引用
          • 简单名称与描述符
      • 方法表集合
        • 字段访问标志
        • 名称与类型常量池引用
        • Code
      • 属性表集合
        • Code属性
          • 异常表
          • LineNumberTable属性
          • LocalVariableTable和LocalVariableTypeTable属性
          • Signature属性
          • StackMapTable属性
        • Exceptions属性
      • SoureceFile及SourceDebugExtension属性
      • ConstantValue属性
      • InnerClasses属性
      • Deprecated及Synthetic属性
      • MethodParameter属性

平台无关性

Java提出一个非常著名的宣传口号就是一次编写,到处运行

Java通过让虚拟机在不同的硬件平台和操作系统都可以载入和执行同一种无关的字节码,说白了只要电脑装上了JVM虚拟机,就可以去运行任何环境写出的字节码,而其他环境不同之处仅仅只是字节码编译器不同

在这里插入图片描述
可以看到,无论任何系统,通过能执行Class字节码,因为虚拟机完全将操作系统屏蔽了起来

Class类文件的结构

Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符,使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有任何空隙存在,也就是说每个Class文件的大小一定是8个字节的倍数,若遇到需要占用8个字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8个字节进行存储

Class文件采用一种类似C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型

  • 无符号数

Class的数据类型

上面提到了,Class文件采用伪结构来存储数据,这种伪结构只有两种数据类型

无符号数

无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数组、索引引用、数量值或者按照UTF-8编码构成字符串值,也就是说无符号数用来存储基本的数据类型

表是由多个无符号数或者其他表作为数据项构成的符合数据类型,为了便于区分,所有表的命名都习惯以**_info**结尾,表一般用于表述有层次关系的复合结构的数据,整个Class文件本质上也可以视作是一张表,表中有无符号数也有其他的表,这张表由下列所示的数据项按严格顺序排列构成

类型名称数量
u4无符号数magic1
u2无符号数minor_version1
u2无符号数major_version1
u2无符号数constant_pool_count1
cp_infocontant_poolconstant_pool_count - 1
u2无符号数access_flags1
u2无符号数this_class1
u2无符号数super_class1
u2无符号数interfaces_count1
u2无符号数interfacesinterfaces_count
u2无符号数fields_count1
field_infofields1
u2无符号数methods_count1
method_infomethodsmethods_count
u2无符号数attributes_count1
attribute_infoattributesattributes_count

要强调的一点,Class的结构不像XML等描述语言,Class是没有任何的分隔符号的,所以对于表的结构,无论是顺序还是数量,甚至于数据存储的字节序这样的细节,都是被严格限定的,哪个字节代表什么含义, 长度是多少,先后顺序是什么,全部都要按约定来,不允许改变

拓展:字节序称为Byte Ording,Class文件使用的字节序为Big-Endian的排序方式,具体顺序是指高位字节在地址最低位,而最低字节在地址最高位来存储数据

魔数与Class文件的版本

每个Class文件的头4个字节被称为魔数(Magic Number),从上表可以看到其是一个U4的无符号数

魔数只有唯一一个作用,确定这个文件实赋为一个能被虚拟机接受的Class文件,也就是说起到了一个身份识别的作用,当然不只有Class文件存在魔数,比如一些GIF或者JPEG等在文件头都存在着魔数。

那为什么不直接使用扩展名来作识别呢?而是要额外使用空间呢?

这是出于安全考虑,因为扩展名可以随便地进行更改,而采用固定的魔数值可以更好识别,且没有去仔细研究过Class文件的一般不知道魔数值

而Class文件的魔数值也很有趣,值为0xCAFEBABY,寓意为咖啡宝贝

魔术后面接着的就两个u2无符号数,minor_version与major_version,这两个无符号数加起来为4个字节,存储着Class文件的版本号,首先前两个字节,即第5和第6个组成的minor_version是次版本号;而后两个字节,即第7和第8个组成的major_version是主版本号

Java的版本号是从45开始的,也就是45.0就代表了JDK1.0,但这里要注意,从JDK1.0~1.1,是使用45.0 ~ 45.3来代表版本号的,在JDK1.1之后的每个Java大版本都会进行加1;并且从中可以看出,高版本的JDK可以向下兼容一部分低版本的JDK,但不能进行向上兼容,这也是为什么IDEA无法使用JDK1.8打开JDK13的java文件,JAVA虚拟机规范了即使Class文件格式并未发生过任何改变,虚拟机也必须拒绝执行超过其版本号的Class文件

常量池

现在前8个字节都已经看了,分别是魔数和Class文件的版本,紧接着就是关于常量池的了

紧接着主次版本号之后的是常量池入口,常量池其实相当于Class文件里得资源仓库,它是Class文件结构中与其他项目关联最多的数据,通常也是占Class文件空间最大的数据项目之一,并且还是在Class文件中第一个出现的表类型数据项目

常量池的组成是由const_pool_count与const_pool组成,所以要使用表来存储

下面就来说明一下这两部分的作用

  • const_pool_count:常量池中常量的数目是不固定的,所以在常量池的入口需要设置一项u2类型的数据,使用这个u2数据代表容量池容量计数值,说白了就是用来统计常量池中的常量数目,const_pool_count一般从1而不是0开始,所以如果这个数为22,那常量数目就是21,常量池容量为什么不从0开始呢?这是因为类里面有自己的常量池,同时类也会去引用其他类的常量池,而0代表的是不引用任何一个常量池项目,也就是自身没有,也不去引用其他常量池,Class文件结构中只有常量池的容量计数是从1开始,而对于其他集合类型,包括接口索引集合、字段表集合、方法表集合等的容量计数都与一般习惯相同,是从0开始

  • const_pool:存放常量的地方,常量池中主要存放两大类常量,字面量和符号引用

    • 字面量更接近于语言的常量概念,比如字符串、final修饰的变量

    • 而符号引用则属于编译原理方面的概念,如下几方面

      • 被模块导出或者开放的包(Package)
      • 类和接口的全限定名(Fully Qualified Name)
      • 字段的名称和描述符(Descriptor)
      • 方法的名称和描述符
      • 方法句柄和方法类型
      • 动态调用点和动态变量
    • 说白了符号引用其实就是一个连接的东西,通过解析这个连接,可以找到属性在内存中的真正地址

    • 为什么会有符号引用呢?这是因为在进行Javac编译的时候,是没有连接步骤的,而是在虚拟机去加载Class文件的时候才会进行动态连接,说白了就是Class文件不会去保存各个静态方法、字段最终在内存中的布局信息,而是保存其符号引用,如果这些符号引用不经过虚拟机在运行期转换是无法得到对应的真正内存地址,也就无法访问调用

常量池中的常量在const_pool中存放,而且每个常量都是一个表,最初的常量表中共有11种结构各不相同的表结构数据,截止JDK13,常量表中已经有17种不同类型的常量

这17类表都有一个共同的特点,表结构起始的第一位是个u1类型的标志位,这个标志位标示着这个是什么表结构(属于17种中的哪种)

下面来看看这几种的表结构

类型标志位描述
CONSTANT_Utf8_info1形容UTF-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_MethodHandle_info15表示方法句柄
CONSTANT_MethodType_info16表示方法类型
CONSTANT_Dynamic_info17表示一个动态计算常量
CONSTANT_InvokeDynamic_info18表示一个动态方法调用点
CONSTANT_Module_info19表示一个模块
CONSTANT_Packeage_info20表示一个模块中开放或者导出的包

这17种常量类型各自有着完全独立的数据结构,所以常量池是很繁琐的

CONSTANT_Class_info

这种常量结构是用来代表一个类或接口的符号引用

它的组成只有两部分

  • tag:标志位,u1类型,用于区分常量类型的,在CONSTANT_Class_info中,该标志位为7
  • name_index:符号引用,u2类型(也就是说使用两个字节来表示一个指针),它指向了常量池中的一个CONSTANT_Utf8_info类型常量,是一个常量索引,该常量代表了类或者接口的全限定名称,这里拓展一下符号引用,符号引用起始是以一组符号来描述引用的目标,这一组符号可以是任何形式的字面量,只要使用时能够无歧义的定位到目标即可,可以看到像这里的符号引用起始就是类的全限定名

CONSTANT_Utf8_info

这种常量结构是用来代表一个UTF8编码的字符串的

它的组成有三部分

  • tag:标志位,u1类型
  • length:字符串的长度(字节为单位),u2类型
  • bytes:u1类型,这里u1类型不是指整个字符串就用一个u1类型结构来存储,而是由多个u1类型来存储,数量由字符串的长度来决定,因为这个是存放使用UTF8缩略编码表示的字符串的地方

拓展:UTF8缩略编码与UTF8编码的区别

  1. 从u0001到u007f之间的字符,也就是1~127的ASCII码,缩略编码是用1个字节表示
  2. 从u0080到u07ff之间的字符,缩略编码使用2个字节表示
  3. 从u0800到uffff之间的所有字符的缩略编码就按照普通UTF8编码规则使用三个字节表示

这里要提一下,对于Class文件,所有的方法、字段等都需要引用CONSTANT_Utf8_info型常量来描述名称,所以对于这种类型常量的最大长度其实就是Java中的方法、字段名的最大长度,而限制了Java中的方法、字段名的最大长度就是CONSTANT_Utf8_info的length属性

CONSTANT_Integer_info

这种常量结构代表一个int值,组成如下

  • tag:类型为u1,标志位
  • bytes:类型为u4,按照高位在前存储的int值,这里u4是4个字节,所以int占用4个字节

CONSTANT_Float_info

这种常量结构代表一个float值,组成如下

  • tag:标志位
  • bytes:类型为u4,按照高位在前存储的float值,所以float占用4个字节

CONSTANT_Long_info

这种常量结构代表一个long值,组成如下

  • tag:标志位
  • bytes:类型为u8,按照高位在前存储的long值,所以long占用8个字节

CONSTANT_Double_info

这种常量结构代表一个double值,组成如下

  • tag:标志位
  • bytes:类型为u8,按照高位在前存储的double值,所以double占用8个字节

CONSTANT_String_info

这种常量结构代表一个字符串,这也是一个索引,指向了CONSTANT_Utf8_info的

  • tag:标志位
  • index:u2类型,指向字符串字面量的索引

CONSTANT_Fieldref_info

这种常量结构用来形容字段的,代表字段的信息,比如字段来自哪个类,名称和类型是什么

  • tag:标志位
  • index:u2类型,指向声明字段的类或者接口描述符的CONSTANT_Class_info(然后CONSTANT_Class_info又指向一个CONSTANT_Utf8_info,CONSTANT_Utf8_info存储的是符号索引)
  • index:u2类型,指向描述字段的CONSTANT_NameAndType_info

CONSTANT_Methodref_info

这种常量结构用来形容方法的,代表方法的信息,比如方法来自哪个类,名称和返回值类型是什么

  • tag:标志位
  • index:u2类型,指向声明方法的类描述符的CONSTANT_Class_info
  • index:u2类型,指向描述方法的CONSTANT_NameAndType_info

CONSTANT_InterfaceMethod-ref_info

这种常量结构也是用来形容方法的,只不过代表的是接口中的放啊

  • tag:标志位
  • index:u2类型,指向声明方法的接口描述符CONSTANT_Class_info
  • index:u类型,指向描述方法的CONSTANT_NameAndType_info

CONSTANT_NameAndType_info

这种 结构是用来形容字段或者方法的名称常量和描述符常量的

  • tag:标志位
  • index:u2类型,指向该字段或者方法名称常量项的索引
  • index:u2类型,指向该字段或者方法描述符的常量项的索引

CONSTANT_MethodHandle_info

这种结构是用来形容给方法句柄的

  • tag:标志位
  • reference_kind:该参数决定了方法句柄的类型,而句柄的类型决定了方法句柄的字节码行为
  • reference_index:常量池的一个有效索引(句柄的作用就是可以访问其他常量池)

CONSTANT_Module_info

这种结构是用来形容模块的,也就是import

  • tag:标志位
  • name_index:指向存储模块名字的CONSTANT_Utf8_info的指针,而CONSTANT_Utf8_info里面是符号引用

CONSTANT_Package_info

这种结构是形容本类的包名称的,对应的就是package

  • tag:标志位
  • name_index:指向存储包名称的CONSTANT_Utf8_info结构

访问标志

常量池之后紧接着的就是访问标志了,访问标志的作用是用于识别一些类或者接口层次的访问信息,比如这个Class是个类还是个接口;访问修饰符是什么;是否是抽象的;是不是被final修饰的

访问标志占用2个字节,对应Class里面的access_flags,类型为u2

具体的标志位如下

标志名称标志值含义
ACC_PUBLIC0x0001是否为Public
ACC_FINAL0x0010是否被声明为final,只有类可以i设置,接口不可以设置
ACC_SUPER0x0020是否允许使用invokespecial字节码指令的新语义
ACC_INTERFACE0x0200是不是一i个接口
ACC_ABSTRACT0x0400是否为abstract类型,只有抽象类和接口这个标志位才会为true
ACC_SYNTHETIC0x1000判断该类是否为用户代码产生,如果是的话就为0,不是的话就为1,也就是标识这个类并非由用户代码产生
ACC_ANNOTATION0x2000标识这是一个注解
ACC_ENUM0x4000标识这是一个枚举
ACC_MODULE0x8000标识这是一个模块

在access_flags中,其实总共有16个标志位可以使用,而直至JDK9当前只定义了9个,没有使用到的标志位要求一律为0

那么才两个字节的access_flags如何去代表那么多含义呢?

从上表中可以看到,标志名称的标志值并不是连续的,而是有一定距离的,并且该距离通常以位数来拉开,比如说我一个0x8421的access_flags,只可以代表其是一个模块、并且为abstract类型、允许使用invokespecial字节码指令、且为public

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

继续往后的部分就是this_class、super_class、interfaces_count和interfaces部分

  • this_class:u2类型,本类索引
  • super_class:u2类型,父类索引
  • interfaces:一组u2类型的数据的集合,接口索引集合

类索引的作用是用于确定这个类的全限定名,而父类索引则是确定这个类的父类的全限定名,由于Java对于类是不允许多继承的,所以父类索引只有一个,除了Object之外,其他的类都有父类,也就是说其他的类的父类索引都不可能为0,而接口索引则存储了该类实现了哪些接口,这些被实现的接口将会按从左到右的顺序排列在接口索引集合中

本类索引、父类索引、接口索引集合都按顺序接着访问标志进行排列

本类索引和父类索引都是u2类型的,里面存储的是指向CONSTANT_Class_info结构的索引,通过该索引是可以找到CONSTANT_Class_info,而CONSTANT_Class_info存储的是指向CONSTANT_utf8_info的索引,CONSTANT_utf8_info里面存储的正式类的全限定名称(一个符号引用)

而对于接口索引集合是分为两部分的

  • interfaces_count:一个u2类型,存储的是类实现接口的数量,称为接口计数器,同时也表示了下面索引表的容量
  • interfaces:u2类型集合,称为接口索引表,存储的也是一个指向CONSTANT_Class_info结构的索引,通过该索引是可以找到对应的CONSTANT_Class_info,而CONSTANT_Class_info存储的是指向CONSTANT_Utf8_info的索引,CONSTANT_Utf8_info里面存储的正是接口的全限定名

字段表集合

上面已经将魔数、Class文件版本、常量、访问标志和类索引、父类索引、接口索引集合排列好了,接下来到类里面自身拥有的字段了,也就是对应fields_count与fields

字段表用于描述接口或者类中声明的变量,对于字段这个概念,字段是包括类级变量和实例级变量(即静态变量和成员变量,静态变量属于类,而成员变量属于实例),但并不包括在方法内部声明的局部变量

字段可以包括下面的信息

  • 字段的作用域,即修饰符(public private protected)

  • 字段的数据类型

  • 字段的名称

  • 是实例变量还是类变量,即有没有被static关键字修饰

  • 是否可变,即有没有被final关键字修饰

  • 是否并发可见,是否强制从主存中读取,即是否被volatile关键字修饰

  • 可否进行序列化,即是否被transient修饰符修饰

对于字段的各种修饰符,对应的其实只是一个布尔值而已,有为1,没有为0,说白了其实各种修饰符对应的只是一个标志位,每个字段都拥有这个标志位;但对于字段中的名称、数据类型、是无法统一起来的,因此只能通过引用常量池的常量来进行描述

所以对于字段表,拥有以下属性

类型名称数量
u2access_flags:字段的修饰符1
u2name_index:字段的名称,指向常量池的一个常量1
u2descriptor_index:字段的描述符,指向常量池的一个常量1
u2attributes_count:额外信息的数量1
attribute_infoattributes:额外信息attributes_count

字段访问标志

对于字段访问标志,因为访问标志有限并且每个字段都有,所以采用标志位的形式,记录在access_flags中(这里的访问标志并不仅仅是权限符,还有静态statc、序列化transient、内存可见性volatile)

字段访问标志使用对应的标志值来表示

标志名称标志值含义
ACC_PUBLIC0x0001字段是否为public
ACC_PRIVATE0x0002字段是否为private
ACC_PROTECTED0x0004字段是否为protected
ACC_STATIC0x0008字段是否为static
ACC_FINAL0x0010字段是否为final
ACC_VOLIATILE0x0040字段是否为volatile
ACC_SYTHETIC0x1000字段是否由编译器自动产生(一般都是代码产生)
ACC_TRANSIENT0x0080字段是否为transient
ACC_ENUM0x4000字段是否为enum

可以看到,这里的标志值也不是连续的,比如access_flags最终组成了0x4080,它只能是为enum类型并且被transient进行修饰,而不会产生其他歧义现象

而对于接口之中的字段,都会有ACC_PUBLIC、ACC_STATIC、ACC_FINAL标志

名称与类型常量池引用

紧接着下来就是name_index与descriptor_index,这两个都是对常量池的引用,分别代表着字段的简单名称以及字段和方法的描述符

简单名称与描述符

之前在常量池中也有提到过简单名称与描述符,但没有具体将其含义,下面就来认识一下这两个概念

**简单名称其实是指:字段名称和没有类型和参数修饰的方法名称;**而描述符则相对复杂一些,描述符是包含详细信息的,描述符的作用是描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值

对于数据类型(这里也包括返回值的显示),有基本数据类型、引用类型和数组类型,对于基本数据类型,描述符采用大写字符来表示(这里的基本数据类型包括void),而如果是引用类型(对象类型)则是以L加对象的全限定名来并表示,详情如下表所示

标识字符含义
Bbyte类型
Cchar类型
Ddouble类型
Ffloat类型
Iint类型
Jlong类型
Sshort类型
Zboolean类型
Vvoid类型
L对象类型,比如返回值为Integer,则为Ljava/lang/Integer

而对于数组类型,每一维度都会使用一个前置的"["字符来表示,比如如果返回值为一个字符串的二维数组,那么标识字符则是[[Ljava/lang/String,但如果是一个整形数组,则是[[I

对于方法,则是按照先参数列表、后返回值的顺序描述,参数列表按照参数的严格顺序放在一组小括号内,比如无参的toString方法,则为()Ljava/lang/String;括号里面的是参数,L代表返回值为引用类型,后面代表引用类型的具体类型,比如一个int(double a),对应二点形式则为(D)I

现在已经知道了简单名称与描述符,简单名称与描述符都只是对应常量池里面的CONSTANT_Utf8_info结构而已,而这里的name_index和descriptor_index是一个指向常量池的简单名称与描述符的索引

字段表中包含的数据一般在descriptor_index就结束了,但在此之后是会跟随一个属性表集合,用来存储一些额外的信息,倘若直接给一个静态变量并且设置了初值,final static int a = 123,那么属性表中可能会存在一个ConstantValue属性,其值指向了常量表中的123

这里要注意,字段表集合中不会列出从父类或者接口那里继承而来的字段,但可能出现原本代码中不存在的字段,比如在内部类中为了保持对外部类的访问性,内部类中会自动添加指向外部类的字段

方法表集合

字段存放在字段表集合中,而方法存放在方法表集合中,并且方法表的描述跟字段表的描述是一样的

类型名称数量
u2access_flags:方法的修饰符1
u2name_index:方法的名称,指向常量池的一个常量1
u2descriptor_index:方法的描述符,指向常量池的一个常量1
u2attributes_count:额外信息的数量1
attribute_infoattributes:额外信息attributes_count

字段访问标志

方法表同样也有字段访问标志,不过字段访问标志跟字段表的有点出入

  • 字段表拥有transient、volatile,但方法表没有,并且字段可能是枚举类型,但方法肯定不会是枚举类型
  • 方法表上添加了synchroniced、native、strictfp和abstract关键字可用

因此会出现一些出入

标志名称标志值含义
ACC_PUBLIC0x0001是否为public
ACC_PRIVATE0x0002是否为private
ACC_PROTECTED0x0004是否为protected
ACC_STATIC0x0008是否为static
ACC_FINAL0x0010是否为final
ACC_Synchronized0x0040是否为synchronized
ACC_SYTHETIC0x1000是否由编译器自动产生(一般都是代码产生)
ACC_VARAGES0x0080方法是否接受不定参数
ACC_BRIDGE0x4000方法是不是由编译器产生的桥接方法
ACC_STRICT0x0800方法是否为strictfp
ACC_ABSTRACT0x0400方法是不是abstract
ACC_Native0x0100方法是否为native

名称与类型常量池引用

与字段表一样,都是使用name_index,descriptor_index来指向常量池中的常量,上面已经详细说明了形式是如何的

Code

至此,方法的名称、返回值、修饰符都已经有地方存储了,那对于方法里面的代码呢?

方法里的Java代码,经过Javac编译器编译成字节码指令之后,会存放在方法属性表集合中的一个名为code的属性里面,所以方法表的属性表其实跟字段表一样,也是去存放扩展的一些额外信息的

而且,与字段表一样,来自父类的方法如果没有进行重写也是不会出现在方法表中的,或者接口中的默认方法没有进行重写也是不会出现在方法表中的

属性表集合

在字段表集合、方法表集合甚至Class文件中都有属性表这个概念,下面就来对这个属性表来分析

Class文件对其他的数据项目要求严格的顺序、长度和内容不同,而属性表没有Class文件那么严格,不要求各个属性表具有严格的顺序,甚至允许只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写入自己定义的属性信息,属性表中的属性现在已经有29项了,下面只挑选一些关键、重要的属性讲解

首先我们要认识属性表的结构,属性表中存放着各个属性,而各个属性的结构如下

类型名称数量
u2attribute_name_index:代表属性的名称,是一个指向常量表CONSTANT_Utf8_info结构的索引1
u4attribute_length:代表属性的长度,以字节为单位1
u1info:代表属性内容,u1类型代表了内容肯定会是1个字节的倍数attribute_length

Code属性

在方法表中提到过,方法表中存储方法的代码的地方是在方法的集合表里面(注意是方法的集合表,每个方法都有自己的集合表),具体来说是集合表中的Code属性,当然如果没有方法代码的话也就没有Code属性表,一个方法对应就是一个Code属性表

下面就来看看Code属性表的结构

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2max_stack1
u2max_locals1
u4code_length1
u1codecode_length
u2exception_table_length1
exception_infoexception_tableexception_table_length
u2attributes_count1
attribute_infoattributesattributes_count

下面来说明一下这几个属性的作用

  • attribute_name_index:代表了属性的名称,指向了常量池的一个CONSTANT_Utf8_info结构的索引,里CONSTANT_Utf8_info里面存储的是固定的Code字符串
  • attribute_length:代表了属性值的长度,说白了就是集合表接下来的属性的长度,可以看到属性的名称与属性值的长度所占用的空间是6个字节(u2+u4),所以属性值的长度等于整个属性表减去6个字节(attribute_length里面就是这个值)
  • max_stack:max_stack代表了操作数栈深度的最大值,每个方法执行时,任意时刻都不会超过这个深度,虚拟机运行的时候会根据这个值去分配栈帧中的操作栈深度
  • max_locals:代表了局部变量表所需的存储空间,方法里面会有变量,这些变量就存放在临时变量表上,max_locals的单位是变量槽,变量槽是虚拟机为局部变量分配内存所使用的最小单位,对于长度不超过32位的数据类型,每个局部变量只会占用一个变量槽,这里要注意的一个地方,变量槽的数量不是方法里面的局部变量的数量来唯一确定的,操作数栈和局部变量表直接决定一个该方法的栈帧所耗费的内存,不必要的操作数栈深度和变量槽数量会造成内存的浪费,而避免浪费的主要做法就是及时回收不再使用的变量槽,当局部变量的作用域范围过了之后,该局部变量所占用的变量槽就要马上进行回收,让其他局部变量可以马上使用,所以,Java编译器会根据变量的作用域来分配变量槽给各个变量进行使用,并且根据同时生存的最大局部变量数量和类型计算出Max_locals的大小
  • code_length:代表了方法经过Java源程序编译后生成的字节码指令的长度,也是以字节为单位,u4为4个字节,理论上存储的最大值为2^32,但JVM虚拟机明确限制了一个方法不允许超过哦65535条字节质量,也就是2 ^ 16,如果超过了这个数量,Javac编译器就会拒绝编译
  • code:代表了方法经过Java源程序编译后生成的字节码指令,code存储着用于存储字节码指令的一系列字节流,字节码指令,顾名思义,就是一个指令就是一个字节码,长度就是一个字节,当JVM读到code里面的一个字节码时就可以找到字节码对应的字节码指令

Code属性可以说是Class文件中最重要的一个属性,如果将Java程序中的信息分为代码和元数据

  • 代码:方法体里面的Java代码
  • 元数据:类信息、字段信息、方法定义以及其他信息

那么Code属性就代表着代码的一部分,而Class文件另外的其他数据项来形容元数据

接下来我们使用一个简单的Java代码来看看

package offer.testSome;/*** @Author: Ember* @Date: 2021/10/26 19:29* @Description:*/
public class TestClass {private int m;public int inc(){return m + 1;}
}

使用Java -v 得到的class文件信息

在这里插入图片描述

可以看到有我们之前提到的版本、还有常量池信息

在这里插入图片描述
接下来就是code信息

这里的code在init方法里面,就是缺省的一个构造函数,但这里有一个其他的点,可以看到,args_size参数竟然为1,代表有一个参数

接下来看看自己写的inc方法

在这里插入图片描述
可以看到,里面的args_size也为1

这是为什么呢?明明两个方法都没有参数,为什么args_size为1,并且locals也给这个变量给了变量槽

这是因为this指针,在类中,我们可以在成员方法使用this指针,但我们没有给this指针一个参数的位置,所以,从这里我们可以看出this指针的实现,通过在Javac编译器编译的时候把this关键字的访问转变为对一个普通方法参数的访问,然后在虚拟机调用实例方法时候自动传入此参数而已,因此在方法里面的code属性中,至少会有一个参数,局部变量表也会预留一个变量槽位来存放对象实例的引用,但这个情况只对成员方法有效,如果改成静态方法,是不会有的

在这里插入图片描述
可以看到,在改为static之后,args_size就为0了,这是因为static修饰后就没有this这个指针变量了

接下来的就是该方法的显示异常处理表集合了,用来存储该方法try捕捉的异常,异常表对于Code属性来说并不是必须存在的,比如上面的栗子就没有异常表生成

异常表

异常表的格式如下所示,总共包含4个字段

类型名称数量
u2start_pc1
u2end_pc1
u2handler_pc1
u2catch_type1

下面就说明一下这4个字段的含义

  • start_pc:try语句位于的行数
  • end_pc:try语句结束的行数,start_pc和end_pc形成了一个行数范围,刚好就是try语句块,只要在这范围之间出现了类型为catch_type的异常或者其子类的异常就会转到handler_pc行继续处理,注意这个行数范围不是指代码,而是指编译成的字节码指令的范围
  • handler_pc:这个是负责记录处理异常是交由第几行实现的
  • catch_type:标识捕捉的异常类型,是一个指向常量池中CONSTANT_Class_info型常量的索引,当catch_type为0时,代表任意的异常情况都会转到handler_pc去进行处理

下面就来看看这个异常表是怎样的

在这里插入图片描述
可以看到,from其实就代表start_pc、to就代表end_pc,target代表的就是handler_pc,type其实对应的是常量池的CONSTANT_Class_info,为一个 符号引用

可以看到从第0条命令到第5条命令,只要在这里出现已经Exception异常,就会交由第6条命令去执行,0~5的命令就是执行逻辑并且返回值而已

加上finally语句之后,就会变成如下这样

在这里插入图片描述
在这里插入图片描述

可以看到,多出了三个any,any代表的就是任何的异常,可以看到一个有趣的现象,我们可以0~6的命令出现了Exception异常会跳到第8条命令去处理,这里与上面不加finally最大的不同就是没有经过return的命令,接下来就是0 ~ 6的命令出现了any异常会跳到了第十五行,然后8~13行的anu异常也会跳到第15行,15 ~ 16行的any异常也会跳到第15行

也就是有三条

  • 0~6的Exception交由8处理,即try语句块
  • 0~6出现不属于Exception的异常,会交由15处理,即try语句块
  • 8~13出现异常,会交由15处理,即catch语句块
  • 15~16的异常也会交由15处理,也就是finally语句块

可能大家这里就会觉得,不是说finally语句块的return会将返回值给截断的吗?但看异常表的情况好像要出现异常才可以走到finally语句块呀,但其实finally的关键字的作用没有那么简单,下面我们仔细分析一下字节码指令

在这里插入图片描述
整个指令执行的过程

  • 获取静态值
  • 取出静态值赋予i
  • i进行自增
  • 对i进行存储
  • 在这里,本来就应该返回值了,但finally语句块导致了这里将i又变为1
  • 然后返回i
  • 接下来给是astore指令,将catch中定义的Exception赋值,并且放到变量槽2中
  • 。。。

可以看到,其实finally会将正常返回值的字节码指令都进行替换,替换成finally里面的返回指令,所以压根不会正常返回,一定会经过finally的return命令

LineNumberTable属性

LineNumberTable属性是用来描述Java源码行号与字节码指令行号之间的对应关系,它并不是运行时必须道德属性,但默认会生成到CLASS文件之中的,我们也可以同属-g:none来取消生成这项信息

如果不选择这个信息,最主要的影响就是当抛出异常的时候,堆栈中是不会显示出错的代码行号,并且在调试程序的时候,也无法按照源码来设置断点

在这里插入图片描述
可以看到,LineNumberTable将代码行号与字节码命令关联在了一起

LineNumberTable的结构如下所示

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2line_number_table_length1
line_number_infoline_number_tableline_number_table_length
  • attribute_name_index:指向一个CONSTANT_Utf8的结构,里面固定的字符串就是LineNumberTable
  • attribute_length:存储的就是字符串的长度,而且是以字节为单位
  • line_number_table_length:存储的是下面line_number_info的长度,而且也是以字节为单位
  • line_number_info:里面包含了两个数据项
    • start_pc:u2类型,里面存储的就是字节码指令的行号
    • line_number:u2类型,里面存储的是源代码的行号,也就是Java源代码的行号
    • 这两个数据项就是上图中的数据项

因为下面的属性都会出现attribute_name_index和attribute_length这两个属性,所以就不会再进行赘述了

LocalVariableTable和LocalVariableTypeTable属性

LocalVariableTable是用来描述栈帧中局部变量表的变量与Java源码中定义的变量名之间的关系,它也不是一个必要的属性,也是可以进行取消生成的,取消的后果是参数名称丢失,看到的只有arg0和arg1这些东西,也就是说占位符取代了原先的参数名,并且对于调试期间无法根据参数名称从上下文获得参数值

在这里插入图片描述

LocalVariableTable的架构如下

类型名称数量
u2attribute_name_index1
u2attribute_length1
u2local_variable_table_length1
local_variable_infolocal_variable_tablelocal_variable_table_length
  • 前两个属性不再赘述

  • local_variable_table_length:代表local_variable_table的长度,单位为字节

  • local_variable_info:存储的就是方法的参数与栈帧的关联

    • start_pc:从第几行的字节码指令行出现,也就是该局部变量的生命周期开始的字节码偏移量,对应start

    • length:代表该局部变量的生命周期的作用范围覆盖的长度,对应length

    • name_index:指向常量池中的CONSTANT_Utf8_info结构的索引,代表了参数的名字,对应name

    • descriptor_index:指向常量池中的CONSTANT_Utf8_info结构的索引,代表了该参数的描述符(前面已经说明过了名字与描述符的区别),对应Signature

    • index:代表了该变量在栈帧的局部变量表中的变量槽的位置,如果该变量的数据类型为64位时,则会占据两个变量槽,即index和Index+1两个变量槽,对应slot

拓展:关于descriptor_index,在JDK5引入泛型之后,descriptor_index其实就被改成了Signature了,也就是特征签名,对于非泛型的数据来说,描述符和特征签名描述的信息是一致的,但如果是泛型,描述符会把泛型的参数化类型给擦除掉,所以不能表示泛型,所以改用了Signature

Signature属性

Signature属性出现在属性表中,是用来支持泛型签名的、记录泛型类型的,后面再仔细研究这个伪泛型、泛型擦除等问题

Signature属性结构如下

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2signature_index1
  • signature_index:是一个指向常量池的CONSTANT_Utf8_info结构的索引,该CONSTANT_Utf8_info表示类签名或方法类型签名或字段类型签名,因为泛型可以放在类上、方法上、还有字段上
StackMapTable属性

这是一个比较复杂的变长属性,该属性会在虚拟机类加载的字节码验证阶段被新类型检查验证器使用,目的在于代替之前比较消耗性能的基于数据流分析的类型推导验证器

这个比较复杂,以后再进行研究。。。

Exceptions属性

在属性表中,接着Code属性就是Exceptions属性了,这里的Exceptions属性与Code属性里面的异常表(Exceptions table)不是同样东西,所以不要搞混了,Exception属性是和Code属性为同一级的东西,而Exceptions table是属于Code属性的

Exceptions属性的作用是列举出方法中可能抛出的受查异常,也就是方法描述时在throws关键字后面列举的异常,结构如下所示

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2number_of_exceptions1
u2exception_index_tablenumber_of_exceptions

比如我给一个方法抛出异常

在这里插入图片描述

可以看到Exceptions的情况了

number_of_exceptions代表方法可能抛出多少种受查异常,每一种受查异常都是使用一个exception_index_table来标识,而exception_index_table是一个指向常量池中的CONSTANT_Class_info型常量的索引,可以看出是一个符号引用

SoureceFile及SourceDebugExtension属性

对应的部分如下

在这里插入图片描述
可以看到SourceFile属性仅仅只是用于记录生成这个Class文件的源码文件名称,并且这个属性也是可选的,对于大多数的类来说,类名和文件名是一致的,除了一些特殊情况,比如内部类,如果不生成这个属性的话,当抛出异常时,堆栈中将不会显示出错代码所属的文件名,并且这个属性还是一个定长的属性

类型名称数量
u2attribute_name_index1
u4attribute_length1
u1sourcefile_index1

sourcefile_index是一个指向常量池的CONSTANT_Utf8_info的索引,里面保存了文件的名称

还有一个SourceDebugExtension属性,是为了方便在编译器和动态生成的Class中加入供程序员使用的自定义内容,用于存储额外的代码调试信息

ConstantValue属性

ConstantValue是用来描述static修饰的变量的,并且是位于字段表上的,并且必须要使用static和final来同时修饰才会出现

在这里插入图片描述

因为我的JDK是ORACLE版本的,ORACLE对于ConstantValue属性的选择是如果同时使用fianl和static来修饰一个变量,并且该变量的数据类型是基本类型或者是String类型的,那么就会生成ConstantValue这个属性

比如我改成Integer类型后,ConstantValue就不会生成了,并且还会多出一个static方法出来

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
该属性的作用就是通知虚拟机自动位静态变量赋值,并且仅仅限制在基本数据类型和String类型,这是因为常量池里面仅仅支持这些基本类型,对于Oracle,如果类变量被final和static修饰,那么就会采用ConstantValue的方式赋值,如果没有final修饰,就会由Clinit方法进行赋值

ConstantValue的结构如下所示

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2constantvalue_index1
  • Constantvalue_index:代表的是一个常量池中一个字面量常量的引用,根据类型的不同,可以是CONSTANT_Long_info、CONSTANT_Integer_info等。。。。

InnerClasses属性

这个属性是用于记录内部类与宿主类之间的关联的,如果一个类中定义了内部类,那么就会生成InnerClasses属性

在这里插入图片描述
InnerClass属性的结构如下所示

类型名称数量
u2attribute_name_index1
u4attribute_length1
u2number_of_classes1
inner_classes_infoinner_classnumber_of_classes
  • number_of_classes:代表需要记录多少个内部类信息
  • inner_classes_info:存储的内部类信息
    • inner_class_info_index:u2类型,指向了常量池的CONSTANT_Class_info结构的索引,代表了内部类的符号引用
    • outer_class_info_index:u2类型,指向了常量池的CONSTANT_Class_info结构的索引,代表了外部类的符号引用
    • inner_name_index:u2类型,指向了常量池的CONSTANT_Utf8_info结构的索引,代表了内部类的名称,如果是一个匿名内部类,这里的索引值为0
    • inner_class_access_flags:u2类型,代表了内部类的访问标志,也就是ACC_PUBLIC那些,与类的access_flags类似

Deprecated及Synthetic属性

Deprecated其实就是代表该类、该方法或者该字段是否已经被弃用,只要打上了@Deprecated注解之后就代表被弃用了

在这里插入图片描述
而Synthetic属性是代表该方法或者字段并不是由用户写的代码产生的,而是由编译器自行添加的,因为这两个属性为布尔类型的,只有有跟没有这两种情况,所以这两个属性的架构都是一样的,且非常简单,仅仅只有attribute_name_index与attribute_length

MethodParameter属性

该属性是存储方法参数名称的,而且是在JDK8之后才添加的,这是由于在Class文件中存储方法的形参名称没有任何的意义,因为给参数起什么名字对于计算机来说没有任何意义,参数的名字仅仅只在源码中进行妥当命名即可,但后面发现Class文件中没有形参的名称带来了诸多的不变,比如反射的时候不能根据Class文件来获取参数名称的

一开始方法参数的名称是存放到localVariableTable属性之中的,但后面发现却不合适,因为localVariableTable是存放在code属性里面的,只有拥有方法体才会有localVariableTable属性,那么对于抽象方法来说,是不存在方法体的,而且也可能会拥有参数的,所以localVariableTable并不合适,所以最后是创建了MethodParameter属性来专门存放形参名称,与Code是一个平级的存在,也就是每个有参方法都有MethodParameter,不会受到Code属性的干扰

看一下存放在LocalVariableTable中的形参名字
在这里插入图片描述

由于没有安装比较新的JDK,所以没看到MethodParameter的细节

MethodParameter的结构如下

类型名称数量
u2attribute_name_index1
u4attribute_length1
u1parameters_count1
parameterparametersparameters_count
  • parameters_count:形参名称的个数
  • parameter:形参名称
    • name_index:u2类型,指向常量池中的CONSTANT_Utf8_info结构的索引,里面存储着形参的名称
    • access_flags:u2类型,代表着形参的状态指示器,包含了三种状态中的一种或者多种
      • ACC_FINAL:表示该参数被final修饰
      • ACC_SYNTHETIC:表示该参数不是源代码生成的,而是编译器自动生成的
      • ACC_MANDATED:表示该参数是在源文件中隐式定义的,比如this关键字

对于Class的结构大概就先认识这么多,感觉已经足够了,本来书上还有模块化相关属性的,个人感觉不太重要

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 攻防世界-如来十三掌

    一看就是佛语,可以用“与佛论禅”解密 第一反应是base64,但是解码失败了 试过很多密码都没有用,后来想到“十三掌”,试试用rot13,或者凯撒密码转13位 但是仍然没有用,后面发现还是要用base64...

    2024/5/2 0:26:58
  2. 【机器学习|数学基础】Mathematics for Machine Learning系列之图论(2):图的矩阵表示

    目录 前言系列文章1.3 图的矩阵表示1.3.1 邻接矩阵无向图的邻接矩阵小结有向图的邻接矩阵小结加权有向图的带权邻接矩阵1.3.2 关联矩阵无向图的关联矩阵有向图的关联矩阵1.3.3 边矩阵结语前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢...

    2024/4/15 19:50:48
  3. C#第一周的学习内容

    C#入门C#的程序结构C#的数据类型数据的显式转换和隐式转换C#周编程总汇本周总结C#的程序结构 C#编程开头一定为using 某空间,意为引用命名空间 接着要有命名空间的声明(一个项目中可以有多个命名空间,一个类只能有一个) 接着要创…...

    2024/4/15 19:50:48
  4. iTerm2安装目录提示和补全插件incr

    incr 是一个目录提示和补全插件。 mkdir ~/.oh-my-zsh/custom/plugins/incr cd ~/.oh-my-zsh/custom/plugins/incr wget -O incr-0.2.zsh http://mimosa-pudica.net/src/incr-0.2.zsh # wget -O ~/.oh-my-zsh/plugins/incr/incr-0.2.zsh http://mimosa-pudica.net/src/incr-0…...

    2024/4/19 7:51:18
  5. 2021-10-29 visual Foxpro连接数据库sql_server并且执行sql语句

    打开vf工具&#xff0c;创建一个程序&#xff0c;然后复制黏贴以下代码 *-- 建立连接 lcDSNLess"driverSQL Server;serverlocalhost;uidSA;pwd你的密码;DATABASE你的数据库" * 声明变量 Public con * 测试是否成功连接 con Sqlstringconnect(lcDSNLess) If con <…...

    2024/4/16 2:37:06
  6. 运维学习笔记10补充——Linux中的网桥设置

    先删除已有网桥&#xff0c;恢复默认的网卡设置。 此时主机只剩下一个ifcfg配置文件&#xff0c;对其进行更改 注意&#xff1a;decice的设备名称为真实存在设备名称&#xff0c;每台主机不同&#xff0c;需要用ifconfig查看 设置完成后保存&#xff0c;然后重新加载两个br0&…...

    2024/4/15 19:50:48
  7. L1-026 I Love GPLT (5 分)

    这道超级简单的题目没有任何输入。 你只需要把这句很重要的话 —— “I Love GPLT”——竖着输出就可以了。 所谓“竖着输出”&#xff0c;是指每个字符占一行&#xff08;包括空格&#xff09;&#xff0c;即每行只能有1个字符和回车。 输入样例&#xff1a; 无 结尾无空…...

    2024/4/5 7:42:36
  8. 防撞基站接线说明

    防撞基站支持2路继电器输出&#xff0c;2路继电器可以单独设置距离控制&#xff0c;每一路可以输出常开和常闭&#xff0c;默认情况下我司只接继电器1&#xff0c;如需要继电器2可自行引出&#xff0c;设备供电支持DC12~24宽电压供电。如下图所示 接线说明&#xff08;如下图所…...

    2024/4/18 2:24:24
  9. 【剑指Offer打卡】24.反转链表

    剑指Offer 24.反转链表 JavaScript剑指Offer题解 &#x1f680;包含数组、对象、链表、堆栈、树等经典题型 ☕️每天一道&#xff0c;轻松不累 &#x1f4ac;详细的题目解析&#xff0c;收藏方便阅读 &#x1f64f;在线star地址 在线阅读地址 在线阅读地址 题目描述 定义一个…...

    2024/4/30 9:13:53
  10. 论文研读(三)

    Online Collective Matrix Factorization Hashing for Large-Scale Cross-Media Retrieval 2020 SIGIR Di Wang XiDian University 概要 通过开发一种高效的在线优化方法&#xff0c;将CMFH扩展为在线学习模式。它增量地更新哈希函数以适应多模态数据流的变化&#xff0c;同…...

    2024/4/15 19:50:53
  11. Android五大布局之一表格布局(TableLayout)

    一.TableLayout(表格布局)常用属性: android:collapseColumns:设置需要被隐藏的列的序号 android:shrinkColumns:设置允许被收缩的列的列序号 android:stretchColumns:设置运行被拉伸的列的列序号 以上这三个属性的列号都是从0开始算的,比如shrinkColunmns = “2”,对应的是第…...

    2024/4/29 10:00:21
  12. leetcode 1560. Most Visited Sector in a Circular Track

    leetcode 1560原题题目大意及思路代码运行截图收获原题 题目大意及思路 题目大意&#xff1a; 给定一个正整数n&#xff0c;和一个rounds数组。n代表马拉松的站点标号为1-N&#xff0c;rounds数组的意义&#xff1a;第i段路程的起点为rounds[i-1]&#xff0c;终点为rounds[i]。…...

    2024/4/20 5:21:38
  13. python实现九九乘法表

    print(九九乘法表&#xff1a;) for x in range(1,10):for y in range(1,x1):# for y in range(1,10):print(x,*,y,"",x*y,end\t)print()print(九九乘法表倒序&#xff1a;) for x in range(9,0,-1): #987654321# print(x,end)for y in range(1,x1):print(x,*,y,&qu…...

    2024/4/20 16:48:22
  14. 【华为机试】公共子串计算

    描述 给定两个只包含小写字母的字符串&#xff0c;计算两个字符串的最大公共子串的长度。 注&#xff1a;子串的定义指一个字符串删掉其部分前缀和后缀&#xff08;也可以不删&#xff09;后形成的字符串。 数据范围&#xff1a;字符串长度&#xff1a;1 < s < 150 进…...

    2024/4/6 6:21:03
  15. DES加解密(详细的加密流程)

    DES介绍一、置换&#xff08;IP置换&#xff09;1.初始置换二、具体步骤1.秘钥初始化2.16轮迭代DES解密介绍 IBM公司成立了研究新密码体制的小组&#xff0c;由Tuchman博士领导&#xff0c;Horst. Feistel进行设计完成了Lucifer 密码。美国国家标准局NBS(美国标准技术研究所NI…...

    2024/4/15 19:51:43
  16. 和海草一起学C语言---一看就懂的选择、循环语句和数组

    ⭐️前言⭐️ 今天继续带大家一起初识C语言。接着上一节内容&#xff0c;今天主要认识一下选择语句、循环语句 and 数组。周五想偷懒&#xff0c;不是&#xff0c;想学习&#xff0c;怎么能浪费大学的美好时光呢&#x1f60f; 一、选择语句&#x1f420; &#x1f43b; 正所谓…...

    2024/4/20 13:58:50
  17. 网络时间服务器的编写

    NTP全称Network Time Protocol&#xff0c;即网络时间同步协议 NTP服务端: import socket from time import strftime ip_port (127.0.0.1, 9000) buf_size 1024 s socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind(ip_port) while True:msg, addr s.recvfrom(bu…...

    2024/4/28 3:44:26
  18. MySQL 高阶语句之函数存储

    目录一、数据库函数1. 数学函数2. 聚合函数3. 字符串函数4. 日期时间函数二、存储过程1. 概述2. 存储过程的优点3. 操作流程4. 存储过程的参数5. 修改存储过程6. 删除存储过程一、数据库函数 1. 数学函数 数据库内存储的记录&#xff0c;经常要进行一系列的算术操作&#xff…...

    2024/4/24 5:12:18
  19. Hive参数优化

    此教程中关于Hive的优化&#xff0c;皆是基于Hive2.x的版本&#xff0c;对于Hive1.x旧版本的优化机制不再复述&#xff08;新版本已改善或变更&#xff09;。另外新版本中默认为开启状态的优化配置项&#xff0c;在工作中无需修改&#xff0c;也不再复述。 一、HDFS副本数 配…...

    2024/4/15 19:51:38
  20. PyQt6简单教程(一)

    目录 正题 安装PyQt6 第一种 第二种 测试安装 结尾 剧透 事先声明 本人说的东西与官方文档基本相似&#xff0c;如果有英语阅读能力&#xff0c;请前往官方API 正题 安装PyQt6 我们有两种安装方法&#xff0c;推荐大家使用第一种 第一种 点击WindowsR&#xff0c;输…...

    2024/4/28 15:24:13

最新文章

  1. 吴恩达机器学习笔记:第 9 周-15 异常检测(Anomaly Detection) 15.1-15.2

    目录 第 9 周 15、 异常检测(Anomaly Detection)15.1 问题的动机15.2 高斯分布 第 9 周 15、 异常检测(Anomaly Detection) 15.1 问题的动机 在接下来的一系列视频中&#xff0c;我将向大家介绍异常检测(Anomaly detection)问题。这是机器学习算法的一个常见应用。这种算法的…...

    2024/5/2 6:26:57
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. git修改某个远端服务器的地址的方式以及4种remote

    假设本地有1个远端仓库&#xff0c;默认一般叫origin&#xff0c;原来对应的git url是&#xff1a;gitxxx.git # 查看方式&#xff1a; git remote -v# 修改方式&#xff1a; git地址url指定远程仓库&#xff1a;&#xff08;常用&#xff09; git remote set-url origin gitn…...

    2024/5/2 5:49:40
  4. 深入浅出 -- 系统架构之微服务中Nacos的部署

    前面我们提到过&#xff0c;在微服务架构中&#xff0c;Nacos注册中心属于核心组件&#xff0c;通常我们会采用高性能独立服务器进行部署&#xff0c;下面我们一起来看看Nacos部署过程&#xff1a; 1、环境准备 因为Nacos是支持windows和Linux系统的&#xff0c;且服务器操作…...

    2024/5/1 13:05:05
  5. STM32实现软件SPI对W25Q64内存芯片实现读写操作

    先看看本次实验的成果吧&#xff1a; 这么简单的一个程序&#xff0c;我学习了一个星期左右&#xff0c;终于把所有的关节都打通了。所有代码都能什么都不看背着敲出来了。为了使自己的记忆更为清晰&#xff0c;特意总结了一个思维导图&#xff0c;感觉自己即便是日后忘记了看一…...

    2024/5/1 12:08:49
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57