本问主要介绍class字节码文件,即实例解析class字节码。
1.class文件
1.1 class文件结构
1.2 class文件实例子
class文件内容为16进制表示,1个字节占8位,能表示两个16进制数,即两个16进制数为1个字节,括号中为注释内容,(代表结构名称,占子节大小)
源码:
public class ByTeCodeTest1 {
public static String str="abc"; public int a = 1; public String demo(String name) {
return name; } public static void main(String[] args) {
ByTeCodeTest1 byTeCodeTest1 = new ByTeCodeTest1(); int b = byTeCodeTest1.a; } }
讯享网
class文件
讯享网(魔数,4)cafe babe (次版本号,2)0000 (主版本号,2)0034(常量池大小,2)0025 (常量池内容) (第一个常量)0a00 0700 1f(第二个常量)09 0003 0020 0700 210a 0003 001f 0800 2209 0003 0023 0700 2401 0003 7374 7201 0012 4c6a 6176 612f 6c61 6e67 2f53 7472 696e 673b 0100 0161 0100 0149 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 254c 636f 6d2f 6a74 2f6c 6561 726e 2f62 7974 6563 6f64 652f 4279 5465 436f 6465 5465 7374 313b 0100 0464 656d 6f01 0026 284c 6a61 7661 2f6c 616e 672f 5374 7269 6e67 3b29 4c6a 6176 612f 6c61 6e67 2f53 7472 696e 673b 0100 046e 616d 6501 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 0d62 7954 6543 6f64 6554 6573 7431 0100 0162 0100 083c 636c 696e 6974 3e01 000a 536f 7572 6365 4669 6c65 0100 1242 7954 6543 6f64 6554 6573 7431 2e6a 6176 610c 000c 000d 0c00 0a00 0b01 0023 636f 6d2f 6a74 2f6c 6561 726e 2f62 7974 6563 6f64 652f 4279 5465 436f 6465 5465 7374 3101 0003 6162 630c 0008 0009 (最后一个常量)0100 106a 6176 612f 6c61 6e67 2f4f 626a 6563 74 (类的访问控制权限)00 21(类名)00 03(父类名)00 07(实现接口个数)00 00(成员属性数量)00 02(第一个成员属性)00 0900 0800 0900 00(第二个成员属性)00 0100 0a00 0b00 00(方法数量)00 04(方法内容)00 0100 0c00 0d00 0100 0e00 0000 3800 0200 0100 0000 0a2a b700 012a 04b5 0002 b100 0000 0200 0f00 0000 0a00 0200 0000 0e00 0400 1000 1000 0000 0c00 0100 0000 0a00 1100 1200 00(第一个方法结束)00 0100 1300 1400 0100 0e00 0000 3600 0100 0200 0000 022b b000 0000 0200 0f00 0000 0600 0100 0000 1300 1000 0000 1600 0200 0000 0200 1100 1200 0000 0000 0200 1500 0900 0100 0900 1600 1700 0100 0e00 0000 5400 0200 0300 0000 0ebb 0003 59b7 0004 4c2b b400 023d b100 0000 0200 0f00 0000 0e00 0300 0000 1700 0800 1800 0d00 1900 1000 0000 2000 0300 0000 0e00 1800 1900 0000 0800 0600 1a00 1200 0100 0d00 0100 1b00 0b00 0200 0800 1c00 0d00 0100 0e00 0000 1e00 0100 0000 0000 0612 05b3 0006 b100 0000 0100 0f00 0000 0600 0100 0000 0f00 0100 1d00 0000 0200 1e
1.3 手动解释class文件字节码
class文件的字节码由上1.1表所示部分组成,如class文件结构表中,常量池大小和接口数量各占两个子节,所以最多只能有65535个常量和最多能实现65535个接口。
1.3.1 魔数
魔数占4个子节且是固定的,在上面字节码文件中找到4个字节:CAFEBABY,它的唯一作用是确定这个文件是否能被虚拟机接受。
1.3.1.1 大端小端
表示从内存中读取数据的方式不同:
大端:高地址存数据的低位,低地址存数据的高位
小端:高地址存数据的高位,低地址存数据的低位
1.3.2 主次版本号
如下表中主次版本号代表的jdk版本

在class文件中找到16进制表示:
次版本号:0000,转为十进制:0;
主版本号:0034,转为十进制:52,
所以该class文件实在jdk1.8下编译生成的。
1.3.3 常量池大小
常量池大小占2子节即:
在class文件中找到为:0025 转为十进制:37

由jclasslib可以看出实际常量池是从所以为1开始的,所以实际只有36个常量。
1.3.4 常量池内容
常量池数据类型:

第一个常量: tag:0a -> 10 -> CONSTANT_Methodref_info index:00 07 -> #7 符号引用 index:00 1f -> #31 符号引用 第二个常量: tag:09 -> 9 -> CONSTANT_Fieldref_info index:0003 -> #3 符号引用 index:0020 -> #32 符号引用 。。。。。 最后一个常量 tag:01 -> 1 -> CONSTANT_utf8_info length:0010 -> 16 bytes:6a 6176 612f 6c61 6e67 2f4f 626a 6563 74 转成字符串 java/lang/Object
1.3.5 类的访问控制权限

00 21 -> ACC_PUBLIC | ACC_SUPER
1.3.6 类名
00 03 -> #3 符号引用指向常量池中索为3的常量 -> com/jt/learn/bytecode/ByTeCodeTest1


1.3.7 父类名
00 07 -> #7 符号引用指向常量池中索为7的常量 -> java/lang/Object

1.3.8 实现接口个数
00 00 未实现接口,占用两个字节所以最多能实现65535个接口
1.3.9 接口信息
未实现接口所以此部分不占用字节
1.3.10 成员属性数量
00 02 由2个成员属性,占用两个字节所以最多有65535属性
1.3.11 成员属性
字段访问权限和基本属性:

字段描述符解释表:

成员属性数据结构:

属性的属性数据结构

第一个成员属性:
access_flags(表示属性的访问控制和基本属性,查看上面的字段访问权限和属性标志表):00 09 -> 00 01 | 00 08 -> public static
name_index(名称再常量池的索引):00 08 -> #8 -> str

讯享网descriptor_index(字段描述符常量池索引):00 09 -> #9 -> Ljava/lang/String; attributes_count(属性的属性数量):00 00 -> 0
第二个成属性:
access_flags: 00 01 -> public
name_index: 00 0a -> #10 ->a
descriptor_index: 00 0b ->#9 -> I
attributes_count: 00 00 -> 0
1.3.12 成员方法数量
1.3.13 成员方法内容
方法访问权限和属性标志

方法数据结构:

方法属性数据结构:

code属性数据结构

LineNumberTable数据结构:

LocalVariableTable数据结构:

解析方法
access_flags:00 01 -> public name_index:00 0c -> #12 -> <init> descriptor_index:00 0d -> #13 -> ()V attributes_count:00 01 -> 1 attribute_info attribute_name_index:00 0e -> #14 -> Code attribute_length:00 00 00 38 -> 56 max_stack:00 02 max_locals:00 01 code_length:00 0000 0a -> 10 code:2a b7 00 01 2a 04 b5 00 02 b1 exception_table_length:00 00 attributes_count:00 02 -> 2 attribute_info: attribute_name_index:00 0f -> #15 -> LineNumberTable attribute_length:00 00 00 0a -> 10 line_number_table_length:00 02 ->2 start_pc:00 00 line_number:00 0e start_pc:00 04 line_number:00 10 attribute_name_index:00 10 -> #16 -> LocalVariableTable attribute_length:00 00 00 0C -> 12 local_variable_table_length:00 01 start_pc: 00 00 length: 00 0a name_index: 00 11 -> #17 -> this descriptor_index: 00 12->#18 -> Lcom/jt/learn/bytecode/ByTeCodeTest1; index: 00 00
第一个方法到此结束。
该字节码文件解析到此,后面不一一解析,有兴趣的可自行解析。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/62949.html