`
cccai_1234
  • 浏览: 25399 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

class文件解析

阅读更多

Class.class文件解析

最近在看jvm相关的书,看到关于class文件结构的部分。就自己写了一个类并编译成class文件尝试着自己来解析一下加深认识和印象(为了方便学习去除了某些重复的方法)。

class文件全部内容如下所示:

CAFEBABE 00000031 00340A00 08002509 00050026 09000500 270A0028 00290700 2A0A002B 002C0A00 2B002D07 002E0700 2F010005 6669656C 64010012 4C6A6176 612F6C61 6E672F53 7472696E 673B0100 06764669 656C6401 00067346 69656C64 01000674 4669656C 64010006 3C696E69 743E0100 03282956 01000443 6F646501 000F4C69 6E654E75 6D626572 5461626C 65010012 4C6F6361 6C566172 6961626C 65546162 6C650100 04746869 73010017 4C636F6D 2F74716D 616C6C2F 74657374 2F436C61 73733B01 00086765 74466965 6C640100 1428294C 6A617661 2F6C616E 672F5374 72696E67 3B010008 73657446 69656C64 01001528 4C6A6176 612F6C61 6E672F53 7472696E 673B2956 01000967 65747346 69656C64 01000973 65747346 69656C64 01000665 7175616C 73010015 284C6A61 76612F6C 616E672F 4F626A65 63743B29 5A010001 6F010012 4C6A6176 612F6C61 6E672F4F 626A6563 743B0100 0661436C 61737301 00086861 7368436F 64650100 03282949 01000A53 6F757263 6546696C 6501000A 436C6173 732E6A61 76610C00 0F00100C 000A000B 0C000D00 0B070030 0C003100 32010015 636F6D2F 74716D61 6C6C2F74 6573742F 436C6173 73070033 0C001C00 1D0C0021 00220100 1A636F6D 2F74716D 616C6C2F 74657374 2F537570 6572436C 61737301 001E636F 6D2F7471 6D616C6C 2F746573 742F5375 70657249 6E746572 66616365 0100106A 6176612F 6C616E67 2F4F626A 65637401 00086765 74436C61 73730100 1328294C 6A617661 2F6C616E 672F436C 6173733B 0100106A 6176612F 6C616E67 2F537472 696E6700 21000500 08000100 09000400 02000A00 0B000000 42000C00 0B000000 0A000D00 0B000000 82000E00 0B000000 07000100 0F001000 01001100 00002F00 01000100 0000052A B70001B1 00000002 00120000 00060001 00000007 00130000 000C0001 00000005 00140015 00000001 00160017 00010011 0000002F 00010001 00000005 2AB40002 B0000000 02001200 00000600 01000000 12001300 00000C00 01000000 05001400 15000000 01001800 19000100 11000000 3E000200 02000000 062A2BB5 0002B100 00000200 12000000 0A000200 00001600 05001700 13000000 16000200 00000600 14001500 00000000 06000A00 0B000100 09001A00 17000100 11000000 1C000100 00000000 04B20003 B0000000 01001200 00000600 01000000 1A000900 1B001900 01001100 00003300 01000100 0000052A B30003B1 00000002 00120000 000A0002 0000001E 0004001F 00130000 000C0001 00000005 000D000B 00000001 001C001D 00010011 00000089 00020003 0000003F 2A2BA600 0504AC2B C6000E2A B600042B B60004A5 000503AC 2BC00005 4D2AB400 02C60011 2AB40002 2CB40002 B60006A7 000F2CB4 0002C700 0704A700 0403AC00 00000200 12000000 12000400 00002300 07002400 18002600 1D002800 13000000 20000300 00003F00 14001500 00000000 3F001E00 1F000100 1D002200 20001500 02000100 21002200 01001100 00003D00 01000100 0000132A B40002C6 000D2AB4 0002B600 07A70004 03AC0000 00020012 00000006 00010000 002E0013 0000000C 00010000 00130014 00150000 00010023 00000002 0024

 

要想知道文件是啥意思首先得知道文件结构是什么样子的,下表是java的class文件格式

 

class文件结构
类型 名称 数量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attribute_count 1
attribute_info attributes attributes_count

 

根据以上表格看到前4个字节为magic魔数字段(每一种文件都会有一种特定的值),这里是CAFEBABE代表是class文件类型。接下来就是次版本和主版本了 00000031为49表示此文件可以被1.5及以上版本的jvm执行。之后就是常量池的数量0034转为十进制值为52即有1-51共51个常量数据。

有关于常量项的数据结构如下表所示:

池中常量项结构
常量 项目 类型 描述
CONSTANT_Utf8_info tag u1 值为1
length u2 UTF-8编码的字符串占用字节数
bytes u1 长度为length的UTF-8编码的字符串
CONSTANT_Integer_info tag u1 值为3
bytes u4 按照高位在前存储的int值
CONSTANT_Float_info tag u1 值为4
bytes u4 按照高位在前存储的float值
CONSTANT_Long_info tag u1 值为5
bytes u8 按照高位在前存储的long值
CONSTANT_Double_info tag u1 值为6
bytes u8 按照高位在前存储的double值
CONSTANT_Class_info tag u1 值为7
index u2 指向全限定名常量项的索引
CONSTANT_String_info  tag u1 值为8
index u2 指向字符串字面值的索引
CONSTANT_Fieldref_info tag u1 值为9
index u2 指向声明字段的类或接口描述符CONSTANT_Class_info的索引项
index u2 指向字段描述符CONSTANT_NameAndType的索引项
CONSTANT_Methodref_info tag u1 值为10
index u2 指向声明方法的类描述符CONSTANT_Class_info的索引项
index u2 指向方法描述符CONSTANT_NameAndType_info的索引项
CONSTANT_InterfaceMethodref_info tag u1 值为11
index u2 指向声明方法的类描述符CONSTANT_Class_info的索引项
index u2 指向方法描述符CONSTANT_NameAndType_info的索引项
CONSTANT_NameAndType_info tag u1 值为12
index u2 指向该字段或方法名称常量项的索引
index u2 指向该字段或方法描述符常量项的索引
CONSTANT_MethodHandle_info tag u1 值为15
reference_kind u1 值必须在1~9之间(包括1和9),它决定了方法句柄的类型。方法句柄类型的值表示方法句柄的字节码行为
reference_index u2 值必须是对常量池的有效索引
CONSTANT_MethodType_info tag u1 值为16
descriptor_index u2 值必须是对当前常量池的有效索引,常量池在该索引处的项必须是CONSTANT_Utf8_info结构,表示方法的描述符
CONSTANT_InvokeDynamic_info tag u1 值为18
bootstrap_method_attr_index u2 值必须是对当前的Class文件中引导方法表的bootstrap_method[]数组的有效索引
name_and_type_index u2 值必须是对当前常量池的有效索引,常量池在该索引出的项必须是CONSTANT_NameAndType_info结构,表示方法名和方法描述符

 

根据以上表格解析出常量数据为

#1 0A 0008 0025 Methodref #8.#37

#2 09 0005 0026 Fieldref #8.#38

#3 09 0005 0027 Fieldref #8.#39

#4 0A 0028 0029 Methodref #40.#41

#5 07 002A Class #42

#6 0A 002B 002C Methodref #43.#44 

#7 0A 002B 002D Methodref #43.#45

#8 07 002E Class #46

#9 07 002F Class #47

#10 01 0005 66 69 65 6C 64 Utf8 field

#11 01 0012 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B Utf8 Ljava/lang/String;

#12 01 0006 76 46 69 65 6C 64 Utf8 vField

#13 01 0006 73 46 69 65 6C 64 Utf8 sField

#14 01 0006 74 46 69 65 6C 64 Utf8 tField

#15 01 0006 3C 69 6E 69 74 3E Utf8 <init>

#16 01 0003 28 29 56 Utf8 ()V

#17 01 0004 43 6F 64 65 Utf8 Code 

#18 01 000F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65 Utf8 LineNumberTable

#19 01 0012 4C 6F 63 61 6C 56 61 72 69 61 62 6C 65 54 61 62 6C 65 Utf8 LocalVariableTable

#20 01 0004 74 68 69 73 Utf8 this

#21 01 0017 4C 63 6F 6D 2F 74 71 6D 61 6C 6C 2F 74 65 73 74 2F 43 6C 61 73 73 3B Utf8 Lcom/tqmall/test/Class;

#22 01 0008 67 65 74 46 69 65 6C 64 Utf8 getField

#23 01 0014 28 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B Utf8 ()Ljava/lang/String;

#24 01 0008 73 65 74 46 69 65 6C 64 Utf8 setField

#25 01 0015 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 56 Utf8 (Ljava/lang/String;)V

#26 01 0009 67 65 74 73 46 69 65 6C 64 Utf8 getsField

#27 01 0009 73 65 74 73 46 69 65 6C 64 Utf8 setsField

#28 01 0006 65 71 75 61 6C 73 Utf8 equals

#29 01 0015 28 4C 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 3B 29 5A Utf8 (Ljava/lang/Object;)Z

#30 01 0001 6F Utf8 o

#31 01 0012 4C 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 3B Utf8 Ljava/lang/Object;

#32 01 0006 61 43 6C 61 73 73 Utf8 aClass

#33 01 0008 68 61 73 68 43 6F 64 65 Utf8 hashCode

#34 01 0003 28 29 49 Utf8 ()I

#35 01 000A 53 6F 75 72 63 65 46 69 6C 65 Utf8 SourceFile

#36 01 000A 43 6C 61 73 73 2E 6A 61 76 61 Utf8 Class.java

#37 0C 000F 0010 NameAndType #15:#16 

#38 0C 000A 000B NameAndType #10:#11

#39 0C 000D 000B NameAndType #13:#11

#40 07 0030 Class #48

#41 0C 0031 0032 NameAndType #49:#50

#42 01 0015 63 6F 6D 2F 74 71 6D 61 6C 6C 2F 74 65 73 74 2F 43 6C 61 73 73 Utf8 com/tqmall/test/Class

#43 07 0033 Class #51

#44 0C 001C 001D NameAndType #28:#29

#45 0C 0021 0022 NameAndType #33:34

#46 01 001A 63 6F 6D 2F 74 71 6D 61 6C 6C 2F 74 65 73 74 2F 53 75 70 65 72 43 6C 61 73 73 Utf8 com/tqmall/test/SuperClass

#47 01 001E 63 6F 6D 2F 74 71 6D 61 6C 6C 2F 74 65 73 74 2F 53 75 70 65 72 49 6E 74 65 72 66 61 63 65 Utf8 com/tqmall/test/SuperInterface

#48 01 0010 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 Utf8 java/lang/Object

#49 01 0008 67 65 74 43 6C 61 73 73 Utf8 getClass

#50 01 0013 28 29 4C 6A 61 76 61 2F 6C 61 6E 67 2F 43 6C 61 73 73 3B Utf8 ()Ljava/lang/Class;

#51 01 0010 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 Utf8 java/lang/String

 

按照class文件结构表格接下来的0021就是u2的access_flags了根据访问标志表对应的标志值应该为0x0020|0x0001即ACC_PUBLIC和ACC_SUPER。之后的0005是u2的this_class对应的是类索引指向的是常量池的一条数据#5。之后的0008是u2的super_class对应的是父类索引指向的是常量池的一条数据#8。接下来的0001是u2的interfaces_count对应的是实现的接口数量,因为类可以实现多个接口所以会有这个字段,这里的值是1说明实现了一个接口。下面的一个u2的数据是0009就是实现的接口的索引指向常量池的一条数据#9。之后的数据0004为fields_count,说明该类共有4个field_info信息。第一个field对应接下来的0002 000A 000B 0000分别对应access_flags、name_index、descriptor_index、attributes_count、attribute值分别为ACC_PRIVATE、#10、#11、0。因为attrbutes_count为0所以就没有attrbute_info信息了。第二个0042 000C 000B 0000对应值ACC_PRIVATE和ACC_VOLATILE、#12、#11、0。第三个000A 000D 000B 0000对应值ACC_PRIVATE和ACC_STATIC、#13、#11、0。第四个0082 000E 000B 0000对应值ACC_PRIVATE和ACC_TRANSIENT、#14、#11、0。

接下来的0007对应的就是method_count信息了,说明共有7个method_info信息。

第一个0001 000F 0010 0001 0011 0000002F 0001 0001 00000005 2A B7 00 01 B1 0000 0002 0012 00000006 0001 0000 0007 0013 0000000C 0001 0000 0005 0014 0015 0000分别对应access_flags、name_index、descriptor_index、attributes_count、attributes值分别为ACC_PUBLIC、#15、#16、1、#17(attribute_name_index常量表查询得到Code属性表)、47(attribute_length)、1(max_stack)、1(max_locals)、5(code_length)、aload_0、invokespecial、#1、return、0(异常表数量)、2(属性表数量)、#18(attibute_name_index常量表查询得到LineNumberTable属性表)、6(attribute_length)、1(line_number_table_length)、0(start_pc字节码行号)、7(line_number源码行号)、#19(attribute_name_index常量表查询得到LocalVariableTable属性表)、12(attribute_length)、1(local_variable_table_length)、0(start_pc变量生命周期开始的字节码偏移量)、5(length变量作用范围覆盖的长度)、#20(name_index)、#21(decriptor_index)、0(index变量在战阵局部变量表中Slot的位置,double和long64位时占用index和index+1)。

第二个0001 0016 0017 0001 0011 0000002F 0001 0001 00000005 2A B4 00 02 B0 0000 0002 0012 00000006 0001 0000 0012 0013 0000000C 0001 0000 0005 0014 0015 0000对应值为ACC_PUBLIC、#22、#23、1、#17、47、1、1、5、aload_0、getfield、#2、areturn、0、2、#18、6、1、0、18、#19、12、1、0、5、#20、#21、0。

第三个0001 0018 0019 0001 0011 0000003E 0002 0002 00000006 2A 2B B5 00 02 B1 0000 0002 0012 0000000A 0002 0000 0016 0005 0017 0013 00000016 0002 0000 0006 0014 0015 0000 0000 0006 000A 000B 0001分别对应值为ACC_PUBLIC(access_flags)、#24(name_index)、#25(descriptor_index)、1(attributes_count)、#17(attribute_name_index常量表查询得到Code属性表)、62(attribute_length)、2(max_stack)、2(max_locals)、6(code_length)、aload_0、aload_1、putfield、#2、return、0(异常表数量)、2(属性表数量)、#18(attibute_name_index常量表查询得到LineNumberTable属性表)、10(attribute_length)、2(line_number_table_length)、0(start_pc字节码行号)、22(line_number源码行号)、5(start_pc字节码行号)、23(line_number源码行号)、#19(attribute_name_index常量表查询得到LocalVariableTable属性表)、22(attribute_length)、2(local_variable_table_length)、0(start_pc变量生命周期开始的字节码偏移量)、6(length变量作用范围覆盖的长度)、#20(name_index)、#21(decriptor_index)、0(index变量在战阵局部变量表中Slot的位置,double和long64位时占用index和index+1)、0(start_pc变量生命周期开始的字节码偏移量)、6(length变量作用范围覆盖的长度)、#10(name_index)、#11(decriptor_index)、1(index变量在战阵局部变量表中Slot的位置,double和long64位时占用index和index+1)。

第四个0009 001A 0017 0001 0011 0000001C 0001 0000 00000004 B2 00 03 B0 0000 0001 0012 00000006 0001 0000 001A分别对应值为ACC_PUBLIC和ACC_STATIC、#26、#23、1、#17(Code)、28、1、0、4、getstatic、#3、areturn、0、1、#18、6、1、0、26。

第五个0009 001B 0019 0001 0011 00000033 0001 0001 00000005 2A B3 00 03 B1 0000 0002 0012 0000000A 0002 0000 001E 0004 001F 0013 0000000C 0001 0000 0005 000D 000B 0000对应值为ACC_PUBLIC和ACC_STATIC、#27、#25、1、#17、51、1、1、5、aload_0、putstatic、#3、return、0、2、#18、10、2、0、30、4、31、#19、12、1、0、5、13、11、0。

第六个0001 001C 001D 0001 0011 00000089 0002 0003 0000003F 2A 2B A6 00 05 04 AC 2B C6 00 0E 2A B6 00 04 2B B6 00 04 A5 00 05 03 AC 2B C0 00 05 4D 2A B4 00 02 C6 00 11 2A B4 00 02 2C B4 00 02 B6 00 06 A7 00 0F 2C B4 00 02 C7 00 07 04 A7 00 04 03 AC 0000 0002 0012 00000012 0004 0000 0023 0007 0024 0018 0026 001D 0028 0013 00000020 0003 0000 003F 0014 0015 0000 0000 003F 001E 001F 0001 001D 0022 0020 0015 0002对应值为ACC_PUBLIC、#28、#29、1、#17、137、2、3、63、aload_0、aload_1、if_acmpne、#5、#4、ireturn、aload_1、ifnull、#14、aload_0、invokevirtual、#4、aload_1、invokevirtual、#4、if_acmpeq、#5、#3、ireturn、aload_1、checkcast、#5、astore_2、aload_0、getfield、#2、ifnull、#17、aload_0、getfield、#2、aload_2、getfield、#2、invokevirtual、#6、goto、#15、aload_2、getfield、#2、ifnotnull、#7、iconst_1、goto、#4、iconst_0、ireturn、0、2、#18、18、4、0、35、7、36、24、39、29、40、#19、32、3、0、63、#20、#21、0、0、63、#30、#31、1、29、34、#32、#21、2。

第七个0001 0021 0022 0001 0011 0000003D 0001 0001 00000013 2A B4 00 02 C6 00 0D 2A B4 00 02 B6 00 07 A7 00 04 03 AC 0000 0002 0012 00000006 0001 0000 002E 0013 0000000C 0001 0000 0013 0014 0015 0000对应值为ACC_PUBLIC、#33、#34、1、#17、61、1、1、19、aload_0、getfield、nop、iconst_m1、ifnull、nop、fconst_2、aload_0、invokevirtual、nop、iconst_4、goto、nop、iconst_1、iconsst_0、ireturn、0、2、#18、6、1、0、46、#19、12、1、0、19、#20、#21、0。

接下来的就是类的attributes信息了,0001为attributes_count值为1。

然后 0023 00000002 0024对应值为#35、2、#36。

分享到:
评论
1 楼 cccai_1234 2016-12-02  
code解析还不完全对,每个字节码指令后的参数还没学习到,所以肯定会有错误

相关推荐

    class文件解析器

    class文件解析器class文件解析器class文件解析器

    class文件解析案例

    通过以上分析,我们可以看到,class文件解析是理解Java运行机制的关键一环,而《深入理解Java虚拟机》一书为我们提供了宝贵的理论基础和实践指导。结合样例数据,读者可以进一步探索和掌握Java虚拟机的内部运作。

    java class文件解析

    Java Class文件解析是Java开发中的一个重要概念,它涉及到Java虚拟机(JVM)如何理解和执行程序的核心机制。这篇博文的链接虽然无法直接访问,但从标题和标签我们可以推测,内容可能涵盖了对Java字节码的深入理解和...

    基于Go的Java Class文件解析工具.zip

    本项目“基于Go的Java Class文件解析工具”旨在利用Go语言开发一个工具,用于解析和理解这些二进制文件,帮助开发者更好地分析和理解Java程序的底层结构。 Go语言是一种静态类型的、编译型的、垃圾回收的语言,具有...

    自己动手写Java虚拟机及class文件解析分析工具(java8运行)

    《自己动手写Java虚拟机及class文件解析分析工具(java8运行)》是一份深入探讨Java虚拟机(JVM)工作原理以及如何解析与分析Java类文件(.class)的资源。通过使用Go语言实现一个简化的JVM,这份资料旨在帮助读者...

    一个简单的class文件解析

    这个简单的`class`文件解析的主题将引导我们深入理解Java虚拟机(JVM)的工作原理,以及如何通过工具来分析这些文件。我们将探讨类文件的结构、字节码和如何使用工具如`javap`来解析它们。 首先,`class`文件的结构...

    Ming:Class文件解析器

    MingClass文件解析器关于对Java编译后的Class文件进行解析版本(更新说明)0.1.0修复读取Double和Long类型时出现找不到指定类型的错误移除jdk9的方法InputStream#readAllBytes(),替换为Files#readAllBytes(),以支持...

    java解析class文件

    Java解析Class文件是Java开发中的一个重要环节,它涉及到对字节码的理解和处理。Class文件是Java编译器将源代码编译后的结果,包含了类的结构信息、方法定义、常量池等关键数据。理解并能解析Class文件,对于进行JVM...

    python实现的简单的class解析以及简单执行class.zip

    在本主题中,我们将探讨如何使用Python来解析Java的Class文件,并对其进行简单的执行。这是一项有趣的技术,可以帮助我们理解Java字节码的工作原理,同时也可以在Python环境中运行Java代码。 首先,Java的Class文件...

    Beyond BCompare4 解压可用 可解析class文件

    Beyond BCompare4 解压可用 可解析class文件 Beyond Compare 是一款强大专业的文件和文件夹对比工具。使用它可以很方便地比较出两个文件或文件夹的差异,相差的每一个字节用颜色加以标识,让您查看方便,支持众多种...

    java反编译工具,直接查看class文件

    class文件变java源代码,可同时打开多个文件,关键字高亮显示

    Jvm之用C#解析class文件

    本篇将深入探讨如何使用C#语言来解析Java的class文件,这是一种跨语言的技术应用,有助于增强开发者对Java字节码的理解和操作能力。 首先,我们需要了解Java类文件的结构。一个`.class`文件是二进制格式的,包含了...

    Android-Java代码解析class文件

    本篇文章将详细探讨如何解析这些class文件,以及在Android开发中可能遇到的相关问题。 1. **Java字节码结构**: - 类文件以魔数`CAFEBABE`开头,用于识别文件格式。 - 接着是版本信息,包括字节码版本号和常量池...

    class文件编译器.zip

    这个压缩包`class文件编译器.zip`很可能包含了关于如何将Java源代码编译成`.class`文件的相关工具和信息。`ReadMe.txt`可能是提供编译过程的说明或者编译器使用的指南。 1. **Java源代码与Class文件**: Java源...

    jd-gui-class解析.zip

    JD-GUI是一款免费且开源的Java反编译器,它能快速地将.class文件解析成可读性强的源代码形式,极大地提升了开发者对二进制字节码的理解效率。 JD-GUI的工作原理主要基于反编译技术,它将Java字节码转换回接近原始的...

    class文件反编译工具

    “class文件反编译工具”是一种实用的开发辅助工具,它允许开发者查看和理解已编译的Java程序内部结构,这对于学习开源库、调试、逆向工程或者分析恶意软件的行为非常有帮助。其中,`jd-gui`是一个常见的开源Java反...

Global site tag (gtag.js) - Google Analytics