Class文件结构和JVM字节码执行

class文件结构

字节码只代表程序逻辑,只是Class文件众多组成部分其中之一。

语言无关性

很多语言都可以编译成class文件,如java,rb,groovy等。
在这里插入图片描述

文件结构

Class文件格式版本号及各部分的数量与大小。
在这里插入图片描述

魔数与版本

在这里插入图片描述

  1. 魔数定义了文件是Java类型的文件。比如在图片文件的开头,也有定义图片的类型的魔数。
  2. 版本号告知JVM是否能执行文件中的代码。比如低版本jdk无法执行高版本jdk编译出的class文件。

关于为什么魔数不叫JAVA叫CAFEBEAN,这是James Gosling 的解释

We used to go to lunch at a place called St Michael’s Alley. According to local legend, in the deep dark past, the Grateful Dead used to perform there before they made it big. It was a pretty funky place that was definitely a Grateful Dead Kinda Place. When Jerry died, they even put up a little Buddhist-esque shrine. When we used to go there, we referred to the place as Cafe Dead. Somewhere along the line, it was noticed that this was a HEX number. I was re-vamping some file format code and needed a couple of magic numbers: one for the persistent object file, and one for classes. I used CAFEDEAD for the object file format, and in grepping for 4 character hex words that fit after “CAFE” (it seemed to be a good theme) I hit on BABE and decided to use it. At that time, it didn’t seem terribly important or destined to go anywhere but the trash can of history. So CAFEBABE became the class file format, and CAFEDEAD was the persistent object format. But the persistent object facility went away, and along with it went the use of CAFEDEAD – it was eventually replaced by RMI.

从网上找了jdk各个版本对应的十六进制数和十进制数
在这里插入图片描述

常量池

结构

在这里插入图片描述

  1. constant_pool_count u2
    从u2的大小可知,常量池最多能包含65536个条目(2^16)。每个条目可以是不同的类型,因此他的长度是可变的。
  2. constant_pool cp_info
常量池名称常量池名称表示值常量池名称表示值
CONSTANT_Utf81UTF-8编码的字符串(2byte)
CONSTANT_Integer3Java int (4 bytes)
CONSTANT_Float4Java float (4 bytes)
CONSTANT_Long5Java long (8 bytes)
CONSTANT_Double6Java double (8 bytes)
CONSTANT_Class7class name
CONSTANT_String8String 常量 – index of a Utf8 entry
CONSTANT_Fieldref9字段引用 – name and type, class
CONSTANT_Methodref10方法引用 – name and type, class
CONSTANT_InterfaceMethodref11接口方法引用
CONSTANT_NameAndType12字段或方法的部分符号引用
  1. 常量池条目
    很多常量池条目引用其他常量池条目。
Fieldref
 index to a Class
 index to a Utf8 (name of class containing it)
 index to a NameAndType
 index to a Utf8 (name of field)
 index to a Utf8 (type descriptor)

类、超类、接口的访问符

(1)this class u2
-指向常量池的Class。
(2)super class u2
-指向常量池的class
(3)interface_count u2
-接口数量
(4)interfaces
-interface_count个interface u2
-每个interface是指向CONSTANT_Class的索引
(5)field count
-字段数量
(6)fields
-field_count个field info
(7)field
-access flags u2
-name index u2
-descriptor index u2
-attributes count u2
-attribute info attributes[attributes count]

字段

方法

方法信息中最主要的是字节码,其次包括

  1. 异常处理器表
  2. 操作数栈与局部变量区大小
  3. 操作数栈的类型记录( StackMapTable, Java 6开始)
  4. 调试用符号信息(如LineNumberTable、 LocalVariableTable),对应Java源代码中“诧句”不“表达式”对应癿信息

属性

有关exception_table 表示,在start_pc和end_pc之间,如果遇到catch_type异常或者它的子异常,则转到handler_pc处理。

不要和Code中的Exception table混淆。

Class文件类型文件校验

在这里插入图片描述

Class文件结构的例子

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

从字节码引出的几个问题

1.为什举ASM无法从接口类型上的方法取得参数的名称?比如Mybatis的接口,反编译后会失去参数名称。
这是因为参数名跟局部变量名都保存在LocalVariableTable;返个属性表跟方法体联系在一起,而接口的方法没有方法体。
2. import时每个类型名都写出来与使用*通配符有什么不同?
从Class文件来看没有任何不同,只不过使用通配符增加了源码中名字冲突的可能性而已。

JVM字节码执行

创建对象

当JVM收到一个new指令等其他5个指令时,会检查指令中的参数在常量池是否有这个符号的引用。
https://crossoverjie.top/JCSprout/#/jvm/newObject

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值