【Java】带你解读字节码(上)

了解字节码
解读字节码(上)
解读字节码(下)

三、java字节码的组成

1.基本数据类型

数据类型含义
u1无符号单字节整数
u2无符号2字节整数
u4无符号4字节整数
u8无符号8字节整数

1Byte=8bit,在十六进制中,需要用两位数来表示1Byte。
一个十六进制数需要4bit来表示。

2.java字节码的格式

类型数量名称含义
u41magic魔数
u21minor_version副版本号
u21major_version主版本号
u21constant_pool_count常量数
cp_infoconstant_pool_count-1constant_pool常量池列表
u21access_flags访问标记
u21this_class当前类
u21super_class父类
u21interfaces_count实现的接口数
u2interfaces_countinterfaces接口列表
u21fields_count字段个数
field_infofields_countfields字段列表
u21methods_count方法个数
method_infomethods_countmethods方法列表
u21attribute_count属性个数
attribute_infoattributes_vountattributes属性列表

3.格式解读

为了节省空间,java对字节码的格式有严格要求,所以我们能够照着这个格式表来对字节码进行解读。
非基础数据类型的类型其实也是有基础数据类型来组成的,也是严格按照一定的格式来存放数据的。
可以看到常量池、接口、字段、方法、属性都是采用数量+数据的格式进行存储的。

四、解读字节码

以上面我们创建的ByteCodeTest.class文件为例。

1.魔数(magic)

cafe babe

这个数是用来表示当前文件类型的,这个是由java之父James Gosling设定的。在代码内部也有魔数,一般被叫做魔法值,一般是指在方法内部的常量值。

2.版本号(version)

0000 0034

副版本为0,主版本为52
对应java1.8(8),这个需要根据主版本跟副版本去查询。

3.常量池(constant_pool)

常量池中存储的是不会发生变化的数据。

常量池基本类型

在这里插入图片描述

常量个数(constant_pool_count)
0016

0x16=22
这里指定了常量的个数,常量的个数为22,#0~#22,实际个数为21
为什么要减一我也不是很懂,有的说是因为#0不作为常量,有的说#0表示什么都不引用。

常量池列表(pool_count)

在观察常量时,需要先根据开头的一个字节判断它是什么类型,然后才能知道它的长度

#1

0a00 0400 12

0x0a=10,对应地找到了CONSTANT_Methodref_info
这个类型会引用两个u2(2bit),也就是8位16进制
所以这里是10个十六进制数表示一个常量

0x0004=4
0x0012=12
所以这个常量引用了#4、#12

全部常量
0a00 0400 12
09 0003 0013 
0700 14
07 0015 
0100 0161
0100 0149 
0100 063c 696e 6974 3e
01 0003 2829 56
01 0004 436f 6465 
0100 0f4c 696e 654e 756d 6265 7254 6162 6c65 
0100 124c 6f63 616c 5661 7269 6162 6c65 5461 626c 65
01 0004 7468 6973 
0100 134c 7465 7374 2f42 7974 6543 6f64 6554 6573 743b 
0100 0367 6574 
0100 0328 2949 
0100 0a53 6f75 7263 6546 696c 65
01 0011 4279 7465 436f 6465 5465 7374 2e6a 6176 61
0c 0007 0008 
0c00 0500 06
01 0011 7465 7374 2f42 7974 6543 6f64 6554 6573 74
01 0010 6a61 7661 2f6c 616e 672f 4f62 6a65 6374 

每一行都代表一个常量
类型为CONSTANT_UTF-8_info还需要另查ACSII码表

4.访问标记(access_flags)

访问标记

标记类型
标志名称值(16进制)位(bit)描述
PUBLIC0x00010000000000000001对应public类型的类
PRIVATE0x00020000000000000010字段为private
PROTECTED0x00040000000000000100字段为protected
STATIC0x00080000000000001000字段为static
FINAL0x00100000000000010000对应类的final声明
SUPER0x00200000000000100000标识JVM的invokespecial新语义
VOLATILE0x00400000000000100000字段是否为volatile
TRANSIENT0x00800000000001000000字段是否为transient
INTERFACE0x02000000001000000000接口标志
ABSTRACT0x04000000010000000000抽象类标志
SYNTHETIC0x10000001000000000000标识这个类并非用户代码产生
ANNOTATION0x20000010000000000000标识这是一个注解
ENUM0x40000100000000000000标识这是一个枚举

访问标记是根据每个bit上的0/1来标记的,从表中可以看出它是以16bit来表示的。

0021

访问标记并不是直接对着表找,就可以找到是属于那个类型的。
0x0021=0000000000100001,可以对照表格找到,它在PUBLIC和SUPER上,所以这个类具有public和super标志

5.当前类(this_class)

当前类
表示指定在常量池的位置

0003

0x0003=3
说明当前类对应#3,也就是
#3

0700 14

这个又指向#20
#20

01 0011 7465 7374 2f42 7974 6543 6f64 6554 6573 74
acsii码表查询结果:test/ByteCodeTest

——————————————————————————————
如果本文章内容有问题,请直接评论或者私信我。
未经允许,不得转载!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员徐小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值