.class字节码解析

.class字节码解析

参考: https://www.jianshu.com/p/e5062d62a3d1

一个.class文件有这么些部分组成

u4 表示4个字节,一个字节是两个16进制。!表示不确定

image.png

大致分为7个部分:

1.魔数和class文件版本(次版本号,主版本号)

2.常量池

3.访问标志

4.类索引,父类索引,接口索引

5.字段表集合

6.方法表集合

7.属性表集合

随机找了个.class文件为例:

cafe babe 0000 0034 003a 0a00 0d00 2009
000c 0021 0900 0c00 2209 0023 0024 0700
250a 0005 0020 0800 260a 0005 0027 0a00
0500 280a 0005 0029 0a00 2a00 2b07 002c
0700 2d07 002e 0100 0169 0100 0149 0100
0179 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 124c 6f63
616c 5661 7269 6162 6c65 5461 626c 6501
0004 7468 6973 0100 064c 5465 7374 3b01
0004 6d61 696e 0100 1628 5b4c 6a61 7661
2f6c 616e 672f 5374 7269 6e67 3b29 5601
0004 6172 6773 0100 135b 4c6a 6176 612f
6c61 6e67 2f53 7472 696e 673b 0100 0174
0100 0a53 6f75 7263 6546 696c 6501 0009
5465 7374 2e6a 6176 610c 0012 0013 0c00
0f00 100c 0011 0010 0700 2f0c 0030 0031
0100 176a 6176 612f 6c61 6e67 2f53 7472
696e 6742 7569 6c64 6572 0100 0568 656c
6c6f 0c00 3200 330c 0032 0034 0c00 3500
3607 0037 0c00 3800 3901 0004 5465 7374
0100 106a 6176 612f 6c61 6e67 2f4f 626a
6563 7401 0014 6a61 7661 2f69 6f2f 5365
7269 616c 697a 6162 6c65 0100 106a 6176
612f 6c61 6e67 2f53 7973 7465 6d01 0003
6f75 7401 0015 4c6a 6176 612f 696f 2f50
7269 6e74 5374 7265 616d 3b01 0006 6170
7065 6e64 0100 2d28 4c6a 6176 612f 6c61
6e67 2f53 7472 696e 673b 294c 6a61 7661
2f6c 616e 672f 5374 7269 6e67 4275 696c
6465 723b 0100 1c28 4929 4c6a 6176 612f
6c61 6e67 2f53 7472 696e 6742 7569 6c64
6572 3b01 0008 746f 5374 7269 6e67 0100
1428 294c 6a61 7661 2f6c 616e 672f 5374
7269 6e67 3b01 0013 6a61 7661 2f69 6f2f
5072 696e 7453 7472 6561 6d01 0007 7072
696e 746c 6e01 0015 284c 6a61 7661 2f6c
616e 672f 5374 7269 6e67 3b29 56(constant pool)00 2100
0c00 0d00 0100 0e00 0200 0200 0f00 1000
0000 0000 1100 1000 00(fileds)00 0200 0100 1200
1300 01(code)00 1400 0000 4100 0200 0100 0000
0f2a b700 012a 04b5 0002 2a05 b500 03b1
0000 0002 0015 0000 000e 0003 0000 0003
0004 0005 0009 0006 0016 0000 000c 0001
0000 000f 0017 0018 0000 0009 0019 001a
0001 0014 0000 0058 0003 0002 0000 001c
033c b200 04bb 0005 59b7 0006 1207 b600
081b b600 09b6 000a b600 0bb1 0000 0002
0015 0000 000e 0003 0000 0009 0002 000a
001b 000b 0016 0000 0016 0002 0000 001c
001b 001c 0000 0002 001a 001d 0010 0001
(attr)0001 001e 0000 0002 001f 

java代码

import java.io.Serializable;

public class Test implements Serializable {

    private int i =1;
    int y = 2;

    public static void main(String[] args) {
        int t = 0;
        System.out.println("hello"+t);
    }
}

第一部分、魔数和class文件版本

魔数:0xCAFEBABE 表示当前文件是否是class文件。

主版本号和次版本号主要区分jdk的版本,次版本号占两个字节0x0000 不做讨论。主版本号占2个字节 0x0034 十进制是52,表示jdk1.8

image.png

第二部分、常量池

常量池有两部分组成,分别是常量池数量和常量池项集合,常量池数量-1表示的是集合的size,由两个字节组成,0x003a十进制表示是21 ,那么常量池项集合个数应该是57
在这里插入图片描述

常量池项集合中的常量池项一共有14中类型,每一种类型都有自己的数据结构,这些数据结构有一个共同点,那就是每个常量池项都会用一个字节(tag),表示是那种常量类型。

​ 字面量:一般指文本字符串,声明的final常量值

​ 符号引用:用一组符号描述引用的目标(类,接口,字段,方法等)

img 常量池中的 14 种常量项的结构总表

第一个元素

​ tag : 0x0a (表示第10种类型)在这里插入图片描述

​ 它的数据结构是
在这里插入图片描述

​ class_index: 0x000d 指向常量池中第13个常量项所表示的信息

​ name_and_type_index: 0x0020 指向常量池中第32个常量项所表示的信息

​ 虽然后面的常量池会解析到,但是过于麻烦 这里我直接用jclasslib插件查看

在这里插入图片描述

在这里插入图片描述

第二个元素

​ tag : 0x09 (表示第9种类型)在这里插入图片描述

它的数据结构是
在这里插入图片描述

​ index: 0x000c 指向常量池中第12个常量项所表示的信息

​ index: 0x0021 指向常量池中第33个常量项所表示的信息

在这里插入图片描述

第三个元素

​ tag : 0x09 (表示第9种类型)在这里插入图片描述

它的数据结构是

在这里插入图片描述

​ class_index: 0x000c 指向常量池中第12个常量项所表示的信息

​ name_and_type_index: 0x0022 指向常量池中第34个常量项所表示的信息

在这里插入图片描述

第四个元素

​ tag : 0x09

​ class_index: 0x0023

​ name_and_type:0x0024

在这里插入图片描述

第五个元素

​ tag : 0x07在这里插入图片描述

​ index: 0x0025

以上5个元素都是符号引用,指向的是常量池中的索引地址,我们来分析一个字面量

第十五个元素

​ tag:0x01

在这里插入图片描述

​ length:0x0001 表示占一个一个字节

​ bytes:0x69 转换成ASCII码是 i

在这里插入图片描述

用jclasslib插件也可以看到在这里插入图片描述

也可以使用jclasslib插件倒推字节码,比如说第18个常量项,表示的是字面量 tag是 01占6个字节那么length就是:0x0006 字面量是 倒推一下16进制就是0x3c696e69743e在这里插入图片描述

在这里插入图片描述

关于常量池的解析就看到这里,后面的常量池项依此类推

第三部分、访问标志

常量池后的两个字节表示访问标志 (access_flags),主要表示类或者接口的访问信息 0x0021 ,访问标志可以进行|运算 0x0021 = 0x0200 | 0x0001img
在这里插入图片描述

第四部分、类索引、父类索引、接口索引

这部分主要用来描述类的继承关系

​ 1.类索引(this_class):u2 数据类型,用于确定这个类的全限定名。 0x000c指向常量池中的第12个常量项,看一下第12个常量项的信息,引用的符号引用时第44个常量项,第44个常量项是字面量,这里直接用jclasslib查看,可以看到类的全限定名。在这里插入图片描述

​ 2.父类索引(super_class):u2 数据类型,用于确定这个类的父类的全限定名。0x000d 指向常量池中的第13个常量项,第13个常量项的信息,引用的符号引用时第45个常量项,第45个常量项是字面量,这里直接用jclasslib查看,可以看到父类的全限定名。默认继承java/lang/Object对象
在这里插入图片描述

​ 3.接口索引(interfaces_count),首先是实现接口的个数0x0001 ,发现实现接口的数量是1,如果是0,则不会有实现接口的集合。

​ 第一个接口的索引是0x000e,使用jclasslib查看

在这里插入图片描述

第五部分、字段表集合

字段表集合用于描述接口或类中声明的变量。这里说的字段包括类级变量(static 修饰)和对象级变量(没有用 static 修饰),但不包括方法中声明的局部变量。

​ 有两部分构成,一部分是字段的数量,还有一部分是字段的集合,集合中的字段项的结构如下

img

​ 字段的描述符对应表

image.png

​ 字段数量(field_count):0x0002

​ 我们看第一个字段:

​ access_flags : 0x0002 表示的是private(第三部分,访问标志的图2)

​ name_index: 0x000f 字段名称是i在这里插入图片描述

​ descripator_index: 0x0010 字段描述符是 l,表示是整数类型在这里插入图片描述

​ attributes_count:0x0000 没有属性表计数器,则属性表也不会有

​ 这里直接用jclasslib查看第二个字段

在这里插入图片描述

第六部分、方法表集合

在字段表之后紧跟着方法表集合,方法表表示类或接口中的方法信息。

方法表集合和上述的字段表集合几乎完全一样,最开始的 2 个字节表示一个方法计数器,在方法计数器之后,才是真正的方法数据项。方法表中的每个方法都用一个 method_info 表示,其数据结构如下:

img

编译器会自动添加实例构造器 方法

方法数量:0x0002

access_flags:0x0001 public的方法

name_index:0x0012 方法名称是 执行时期: 对象的初始化阶段 在这里插入图片描述

descripor_index:0x0013 ()V表示f方法 void methodName() 写个小案例:main方法的描述符

​ void main(String[] args) ([L/java/lang/String;)V

在这里插入图片描述

attributes_count:0x00001 表示有一个属性

attribute_name_index:0x0014 值是Code 说明此属性是方法的字节码描述 Code 属性

image.png

attribute_name_index:0x0014 表示code

attribute_length:0x00000041 占用65个字节

max_stack(操作数栈):0x0002

max_locals(局部变量表):0x0001

code_length : 0x0000000f 15个字节

code:0x2a b700 012a 04b5 0002 2a05 b500 03b1 参考: https://www.cnblogs.com/longjee/p/8675771.html

​ 比如0x2a并表示的是在这里插入图片描述

​ 具体的使用jclasslib查看
在这里插入图片描述

exception_code_length:0x0000 没有异常(try/catch)

attribute_count:0x0002 属性占两个字节 code属性的属性

在这里插入图片描述

行号,抛出异常的时候有用

image.png

局部变量表,存储局部变量的参数

image.png

第七部分、属性表集合

在 class 文件、字段表、方法表都可以携带自己的属性表集合,用以描述某些场景专有的信息。

属性表的格式是相对固定的,包括三部分内容:

  • 一个 u2 的 attribute_name_index 指向常量池中的一个 UTF-8 字符串常量表示一个属性名称

  • 一个 u4 的数据类型表示 attribute_length 表示该属性值的字节长度

  • 该长度的属性值信息,结构如下图所示:

    img

    0x0001 001e 0000 0002 001f

(img-aUkiwifK-1598687431438)]

第七部分、属性表集合

在 class 文件、字段表、方法表都可以携带自己的属性表集合,用以描述某些场景专有的信息。

属性表的格式是相对固定的,包括三部分内容:

  • 一个 u2 的 attribute_name_index 指向常量池中的一个 UTF-8 字符串常量表示一个属性名称

  • 一个 u4 的数据类型表示 attribute_length 表示该属性值的字节长度

  • 该长度的属性值信息,结构如下图所示:

    [外链图片转存中...(img-JQvp8jIo-1598687431438)]

    0x0001 001e 0000 0002 001f

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值