首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

class资料分析

2013-10-08 
class文件分析本文通过分析一个简单java类文件的字节码,希望借此能快速了解java类文件格式为了分析字节码,

class文件分析

本文通过分析一个简单java类文件的字节码,希望借此能快速了解java类文件格式

为了分析字节码,必须有一个整体的格式如下:

class资料分析


以上面的表作为分析的基础,开始行动!


一段简单的java代码

123456789package org.kaka.clazz;                                                                                                                                           public class TestClass {        private int m;                                                                                                                                                            public int inc(){                return m+1;        }}


查看字节码

123456789101112131415161718192000000000  ca fe ba be 00 00 00 32  00 13 0a 00 04 00 0f 09  |.......2........|00000010  00 03 00 10 07 00 11 07  00 12 01 00 01 6d 01 00  |.............m..|00000020  01 49 01 00 06 3c 69 6e  69 74 3e 01 00 03 28 29  |.I...<init>...()|00000030  56 01 00 04 43 6f 64 65  01 00 0f 4c 69 6e 65 4e  |V...Code...LineN|00000040  75 6d 62 65 72 54 61 62  6c 65 01 00 03 69 6e 63  |umberTable...inc|00000050  01 00 03 28 29 49 01 00  0a 53 6f 75 72 63 65 46  |...()I...SourceF|00000060  69 6c 65 01 00 0e 54 65  73 74 43 6c 61 73 73 2e  |ile...TestClass.|00000070  6a 61 76 61 0c 00 07 00  08 0c 00 05 00 06 01 00  |java............|00000080  18 6f 72 67 2f 6b 61 6b  61 2f 63 6c 61 7a 7a 2f  |.org/kaka/clazz/|00000090  54 65 73 74 43 6c 61 73  73 01 00 10 6a 61 76 61  |TestClass...java|000000a0  2f 6c 61 6e 67 2f 4f 62  6a 65 63 74 00 21 00 03  |/lang/Object.!..|000000b0  00 04 00 00 00 01 00 02  00 05 00 06 00 00 00 02  |................|000000c0  00 01 00 07 00 08 00 01  00 09 00 00 00 1d 00 01  |................|000000d0  00 01 00 00 00 05 2a b7  00 01 b1 00 00 00 01 00  |......*.........|000000e0  0a 00 00 00 06 00 01 00  00 00 03 00 01 00 0b 00  |................|000000f0  0c 00 01 00 09 00 00 00  1f 00 02 00 01 00 00 00  |................|00000100  07 2a b4 00 02 04 60 ac  00 00 00 01 00 0a 00 00  |.*....`.........|00000110  00 06 00 01 00 00 00 07  00 01 00 0d 00 00 00 02  |................|00000120  00 0e                                             |..|00000122

step 1) java magic number

      首先的四个字节0x ca fe ba be 即class文件的magic number


      step2) java version

          接下来的四个字节0x 00 00 00 32 即class文件的版本号(可参看class文件的版本号列表)

          class资料分析

          step3) 常量池

                  接下来是描述常量表的长度0x 00 13,一共是(19-1)项,人肉分析如下

              第1项

                tag: 0x 0a ,CONSTANT_Methodref_info即方法声明

                index: 0x 00 04,指向常量池中CONSTANT_Class_info,见常量池第4项

                index: 0x 00 0f,指向常量池中CONSTANT_NameAndType_info见常量池第15项

                第2项

                  tag 0x 09,CONSTANT_Fieldref_info即字段声明

                  index: 0x 00 03,指向常量池中CONSTANT_Class_info,见常量池第3项

                  index: 0x 00 10,指向常量池中CONSTANT_NameAndType_info见常量池第16项

                  第3项

                    tag:0x 07,CONSTANT_Class_info即类声明

                    index: 0x 00 11,指向常量池中的CONSTANT_Utf8_info,第17项

                    第4项

                      tag:0x 07,CONSTANT_Class_info即类声明

                      index: 0x 00 12,指向常量池中的CONSTANT_Utf8_info,第18项

                      第5项

                        tag:0x 01,CONSTANT_Utf8_info即字符串说明

                        length: 0x 00 01 ,长度为1个字节

                        bytes: 0x 6d, 内容为"m"

                        第6项

                          tag:0x 01,CONSTANT_Utf8_info即字符串说明

                            length: 0x 00 01 ,长度为1个字节

                              bytes: 0x 49, 内容为"I"

                              第7项

                                tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                length: 0x 00 06 ,长度为6个字节

                                bytes: 0x 3c 69 6e  69 74 3e, 内容为"<init>"

                                第8项

                                  tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                  length: 0x 00 03 ,长度为3个字节 

                                  bytes: 0x 28 29 56 内容为"()V"

                                  第9项

                                    tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                    length: 0x 00 04 ,长度为4个字节 

                                    bytes: 0x 43 6f 64 65 内容为"Code"

                                    第10项

                                      tag:0x 01,CONSTANT_Utf8_info即字符串说明  

                                      length: 0x 00 0f ,长度为15个字节 

                                      bytes: 0x 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62  6c 65内容为"LineNumberTable"  

                                      第11项

                                        tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                        length: 0x 00 03,长度为3个字节

                                        bytes: 0x 69 6e 63 内容为"inc"

                                        第12项

                                          tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                          length: 0x 00 03,长度为3个字节

                                          bytes: 0x 28 29 49 内容为"()I"

                                          第13项

                                            tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                            length: 0x 00 0a,长度为10个字节

                                            bytes: 0x 53 6f 75 72 63 65 46  69 6c 65内容为"SourceFile"

                                            第14项

                                              tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                                length: 0x 00 04,长度为14个字节

                                                  bytes: 0x 54 65  73 74 43 6c 61 73 73 2e  6a 61 76 61内容为"TestClass.java"

                                                  第15项

                                                    tag:0x 0c,CONSTANT_NameAndType_info即字段或者方法说明

                                                    index:0x 00 07 ,字段或者方法常量索引,见常量池第7项

                                                    index:0x 00 08,字段或者方法常量索引,见常量池第8项

                                                    第16项

                                                      tag:0x 0c,CONSTANT_NameAndType_info即字段或者方法说明

                                                      index:0x 00 05 ,字段或者方法常量索引,见常量池第5项

                                                      index:0x 00 06,字段或者方法常量索引,见常量池第6项

                                                        第17项

                                                          tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                                          length: 0x 00 18,长度为24个字节

                                                          bytes: 0x 6f 72 67 2f 6b 61 6b  61 2f 63 6c 61 7a 7a 2f 54 65 73 74 43 6c 61 73  73内容为"org/kaka/clazz/TestClass"

                                                          第18项

                                                            tag:0x 01,CONSTANT_Utf8_info即字符串说明

                                                            length: 0x 00 10,长度为16个字节

                                                            bytes: 0x 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62  6a 65 63 74 内容为"java/lang/Object"


                                                            可以看出

                                                              CONSTANT_Methodref_info、CONSTANT_Fieldref_info都 依赖于CONSTANT_Class_info、CONSTANT_NameAndType_info

                                                              CONSTANT_Class_info依赖于CONSTANT_Utf8_info,后者用于声明类的名字

                                                              CONSTANT_NameAndType_info依赖于两个CONSTANT_Utf8_info

                                                                第一个CONSTANT_Utf8_info用于说明方法或者字段的名字

                                                                第一个CONSTANT_Utf8_info用于说明方法的入参以及返回类型或者字段的类型

                                                                列举常量池结构

                                                                class资料分析



                                                                可以对比下javap的结果

                                                                12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849Compiled from "TestClass.java"public class org.kaka.clazz.TestClass extends java.lang.Object  SourceFile: "TestClass.java"  minor version: 0  major version: 50  Constant pool:const #1 = Method   #4.#15; //  java/lang/Object."<init>":()Vconst #2 = Field    #3.#16; //  org/kaka/clazz/TestClass.m:Iconst #3 = class    #17;    //  org/kaka/clazz/TestClassconst #4 = class    #18;    //  java/lang/Objectconst #5 = Asciz    m;const #6 = Asciz    I;const #7 = Asciz    <init>;const #8 = Asciz    ()V;const #9 = Asciz    Code;const #10 = Asciz   LineNumberTable;const #11 = Asciz   inc;const #12 = Asciz   ()I;const #13 = Asciz   SourceFile;const #14 = Asciz   TestClass.java;const #15 = NameAndType #7:#8;//  "<init>":()Vconst #16 = NameAndType #5:#6;//  m:Iconst #17 = Asciz   org/kaka/clazz/TestClass;const #18 = Asciz   java/lang/Object;                                                                                           {public org.kaka.clazz.TestClass();  Code:   Stack=1, Locals=1, Args_size=1   0:   aload_0   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V   4:   return  LineNumberTable:   line 3: 0                                                                                                                                                                                      public int inc();  Code:   Stack=2, Locals=1, Args_size=1   0:   aload_0   1:   getfield    #2; //Field m:I   4:   iconst_1   5:   iadd   6:   ireturn  LineNumberTable:   line 7: 0                                                                                                                                                                                      }

                                                                两者是一致的 



                                                                step4) 访问标志

                                                                    接下来的两个字节0x 00 21是由下标中的0x 00 01 | 0x 0020计算出来的,表类是public 的,且是jdk1.2以后的编译器编译出来的



                                                                访问标志 标志名称标志值含义ACC_PUBLIC0x0001是否为public类型ACC_FINAL0x0010是否被声明为final,只有类可以设置,接口不能设置该标志ACC_SUPER0x0020

                                                                是否允许使用invokespecial字节码指令(查了一下该命令的作用为"调用超类的构造

                                                                方法,实例的构造方法,私有方法"),JDK1.2以后的编译器编译出来的class文件

                                                                该标志都为真

                                                                ACC_INTERFACE0x0200标识这是一个接口 ACC_ABSTRACT0x0400

                                                                 是否被声明为abstract类型,对于接口和抽象类来说此标志

                                                                为真,其他类为假

                                                                ACC_SYNTHETIC0x1000 标识这个类并非由用户代码生成ACC_ANNOTATION0x2000 标识这是一个注解ACC_ENUM0x4000 标识这是一个枚举


                                                                step5)  类信息


                                                                  头两个字节0x 00 03,指向常量池中的第3项,即类名

                                                                  接下来的两个字节 0x 00 04 指向常量池中的第4项,即父类名

                                                                  接下来的两个字节 0x 00 00 表示类实现的接口的个数,本例子中为0,如果有的n个话,后面还会有2n个字节的常量池索引

                                                                  step 6)字段信息

                                                                     头两个字节 0x 00 01 字段的个数,本例中为1

                                                                      接下来就是1个field_info结构

                                                                      头两个字节 0x 00 02 表示accss_flags,即private

                                                                      接下来0x 00 05表示字段名,指向常量池的第5项,即本例中"m"

                                                                      接下来的0x 00 06 表示字段的描述信息,指向常量池的第6项,即本例中"I" ,表示是int类型

                                                                      接下来的0x 00 00 表示字段的属性信息(用于扩展或者补充说明字段信息)的个数,本例中为0,如果有n个的话,后面还会有n个attribute_info结构

                                                                      step 7) 方法信息

                                                                        头两个字节为0x 00 02,表示方法的个数,本例中为2

                                                                        接下来是两个method_info结构

                                                                          第1个method_info结构

                                                                            头两个字节0x 00 01 表示accss_flags,即public 方法

                                                                            接下来0x 00 07表示方法名,指向常量池的第7项,即本例中"<init>"

                                                                            接下来的0x 00 08 表示方法的描述信息,指向常量池的第8项,即本例中"()V" ,表示是一个没有参数,返回类型为void的方法

                                                                            接下来的0x 00 01表示方法的属性信息的个数,本例中为1

                                                                            接下是1个attribute_info结构

                                                                              0x 00 09表示属性名,指向常量池的第9项,即Code,表示方法的代码

                                                                              0x 00 00 00 1d 表示该属性的长度,即29个字节

                                                                              0x 00 01 表示max_stack 

                                                                              0x 00 01 表示max_locals

                                                                              0x 00 00 00 05 表示code_length, 即该方法的代码为编译后为5个字节

                                                                              0x 2a b7  00 01 b1 即代码

                                                                              0x 00 00 表示 没有异常信息

                                                                              0x 00 01 表示有一个属性信息

                                                                              接下是1个attribute_info结构

                                                                                0x 00 0a 表示属性名,指向常量池的第10项,即LineNumberTable,表示方法的行号

                                                                                0x 00 00 00 06 表示该属性的长度,即6个字节

                                                                                0x 00 01 表示有1行

                                                                                0x 00  00 表示字节码为第0行

                                                                                0x 00 03 表示上面的字节码为第0行对应源码中的第3行

                                                                                第2个method_info结构

                                                                                  头两个字节00 01 表示accss_flags,即public 方法

                                                                                  接下来0x 00 0b表示方法名,指向常量池的第11项,即本例中"inc"

                                                                                  接下来的0x 00 0c 表示方法的描述信息,指向常量池的第12项,即本例中"()I" ,表示是一个没有参数,返回类型为int的方法

                                                                                  接下来的0x 00 01表示方法的属性信息的个数,本例中为1

                                                                                  接下是1个attribute_info结构

                                                                                    0x 00 09表示属性名,指向常量池的第9项,即Code,表示方法的代码

                                                                                    0x 00 00 00 1f 表示该属性的长度,即31个字节

                                                                                    0x 00 02 表示max_stack

                                                                                    0x 00 01 表示max_locals

                                                                                    0x 00 00 00 07 表示code_length, 即该方法的代码为编译后为7个字节

                                                                                    0x 2a b4 00 02 04 60 ac 即代码

                                                                                    0x 00 00 表示 没有异常信息

                                                                                    0x 00 01 表示有一个属性信息

                                                                                    接下是1个attribute_info结构

                                                                                      0x 00 0a 表示属性名,指向常量池的第10项,即LineNumberTable,表示方法的行号

                                                                                      0x 00 00 00 06 表示该属性的长度,即6个字节

                                                                                      0x 00 01 表示有1行

                                                                                      0x 00  00 表示字节码为第0行

                                                                                      0x 00 07 表示上面的字节码为第0行对应源码中的第7行

                                                                                      step 8) 属性信息

                                                                                        头两个字节为0x 00 01,表示有一个属性

                                                                                        接下是1个attribute_info结构

                                                                                          0x 00 0d表示属性名,指向常量池的第13项,即SourceFile,表示类的源文件

                                                                                          0x 00 00 00 02,属性长度,即接下来的字节个数

                                                                                          0x 00 0e 表示源文件名,指向常量池的第14项,即"TestClass.java"



                                                                                          小结   


                                                                                            如果想分析类文件,大部分情况下按字节分析,直接使用javap即可,但如果知道字节码也可以更好的了解javap的结果 

                                                                                            几个种要的结构需要了解,本文就不一一列举具体信息(这个网上到处都是)

                                                                                              method_info

                                                                                                会包含attribute_info

                                                                                                filed_info

                                                                                                  会包含attribute_info

                                                                                                  attribute_info

                                                                                                    共有好几种attribute,本例中就用到了Code,LineNumberTable,SourceFile,每种不同的属性结构都不一样

                                                                                                    特别Code类型的attribute_info,编译过后的字令码就存放在里面

                                                                                                    另外还有LineNumberTable以及本例中未提到的LocalVariableTable都是和调试息息相关的

                                                                                                    有可能会嵌套attribute_info

热点排行