Java字节码(class)文件结构解析

字节码

字节码文件

文件格式

Java编译后的字节码文件格式,其文件结构定义如下:

ClassFile {

    u4             magic;

    u2             minor_version;

    u2             major_version;

    u2             constant_pool_count;

    cp_info        constant_pool[constant_pool_count-1];

    u2             access_flags;

    u2             this_class;

    u2             super_class;

    u2             interfaces_count;

    u2             interfaces[interfaces_count];

    u2             fields_count;

    field_info     fields[fields_count];

    u2             methods_count;

    method_info    methods[methods_count];

    u2             attributes_count;

    attribute_info attributes[attributes_count];

}

以下面一个最简单的一个类为例,在下面这个类中,只通过class修饰定义了一个类,其中没有定义任何常亮,变量以及方法:

class SimpleClass {

}
编译
反汇编如下:
>javap -c SimpleC
lass
Compiled from "SimpleClass.java"
class SimpleClass {
  SimpleClass();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":
()V
       4: return
}
以16进制文件打开生成的class文件如下:


 
 

魔数(magic):

4bytes, 0xCAFEBABE 

版本(version):

包括主版本号和小版本号

小版本号(minor version):

2bytes,0x0000

主版本号(major version):

2bytes,0x0034

常量池:

常量池通过一个数组来保存各个常量,数组的大小-1就是常量池常量个数。针对不同类型的常量通过tag来表示。

常量池常量个数(constant pool count):

0x000D,转换为10进制就是13,

常量池(constant pool):

常量tag:

0x0A,表示一个CONSTANT_Methodref类型的常量

class_index:

0x0003,

name_and_type_index:

0x000A

常量tag:

0x07,表示一个CONSTANT_Class类型的常量

name_index:

0x000B,

常量tag:

0x07,表示一个CONSTANT_Class类型的常量

name_index:

0x000C

常量tag:

0x01, 表示一个CONSTANT_Utf8类型的常量

length:

0x0006, 表示字符串长度

bytes[length]:

0x3C696E69743E,表示字符串“<init>”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x0003,表示字符串长度

bytes[length]:

0x282956,表示字符串“()V”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x0004,表示字符串长度

bytes[length]:

0x436F6465,表示字符串“Code”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x000F,表示字符串长度

bytes[length]:

0x4C696E654E756D6265725461626C65,表示字符串“LineNumberTable”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x000A,表示字符串长度

bytes[length]:

0x536F7572636546696C65,表示字符串“SourceFile”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x0010,表示字符串长度

bytes[length]:

0x53696D706C65436C6173732E6A617661,表示字符串“SimpleClass.java”

常量tag:

0x0C,表示一个CONSTANT_NameAndType类型的常量

name_index:

0x0004,

descriptor_index:

0x0005,

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x000B, 表示字符串长度

bytes[length]:

0x53696D706C65436C617373,表示字符串“SimpleClass”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x0010,表示字符串长度

bytes[length]:

0x6A6176612F6C616E672F4F626A656374,表示字符串“java/lang/Object”

访问控制修饰标志(access_flags):

0x0020

this_class:

0x0002

super_class:

0x0003

interfaces_count:

0x0000

interfaces[interfaces_count]:

fields_count:

0x0000

fields[fields_count]:

methods_count:

0x0001

methods[methods_count]:

方法:

access_flags:

0x0000

name_index:

0x0004

descriptor_index:

0x0005

attributes_count:

0x0001

attributes[attributes_count]:

attribute_name_index:

0x0006

attribute_length:

0x0000001D,表示29

info[attribute_length]:

0x00010001000000052AB70001B100000001000700000006000100000001

对info[attribute_length]的说明:Code_attribute

attribute_name_index:

就是上面对应的attribute_name_index:0x0006

attribute_length:

就是上面对应的attribute_length:0x0000001D,表示29

max_stack:

0x0001

max_locals:

0x0001

code_length:

0x00000005

code[code_length]:

0x2AB70001B1

从这里可以看出这个方法对应的代码指令就是:0x2AB70001B1,具体是些什么指令呢?

经过分析的结果就是:

0: aload_0
1: invokespecial #1
4: return

前面的数字表示对应的指令所占用的字节数,加起来正好5个字节。aload_0对应0x2A,invokespecial #1对应0xB70001,其中0xB7就表示invokespecial指令,return对应0xB1。这里主要就是调用了Object的无参构造方法,然后返回。

exception_table_length:

0x0000

{   u2 start_pc;

    u2 end_pc;

    u2 handler_pc;

    u2 catch_type;

} exception_table[exception_table_length]:

attributes_count:

0x0001

attributes[attributes_count]:

attribute_name_index:

0x0007

attribute_length:

0x00000006

info[attribute_length]:

0x000100000001

attributes_count:

0x0001

attributes[attributes_count]:

attribute_name_index:

0x0008

attribute_length:

0x00000002

info[attribute_length]:

0x0009

到这里整个字节码class文件就全部分析完了。

参考文章:Chapter 4. The class File Format,https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

字节码

字节码文件

文件格式

Java编译后的字节码文件格式,其文件结构定义如下:

ClassFile {

    u4             magic;

    u2             minor_version;

    u2             major_version;

    u2             constant_pool_count;

    cp_info        constant_pool[constant_pool_count-1];

    u2             access_flags;

    u2             this_class;

    u2             super_class;

    u2             interfaces_count;

    u2             interfaces[interfaces_count];

    u2             fields_count;

    field_info     fields[fields_count];

    u2             methods_count;

    method_info    methods[methods_count];

    u2             attributes_count;

    attribute_info attributes[attributes_count];

}

以下面一个最简单的一个类为例,在下面这个类中,只通过class修饰定义了一个类,其中没有定义任何常亮,变量以及方法:

class SimpleClass {

}
编译 反汇编如下:
>javap -c SimpleC
lass
Compiled from "SimpleClass.java"
class SimpleClass {
  SimpleClass();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":
()V
       4: return
}
>javap -c SimpleC lass Compiled from "SimpleClass.java" class SimpleClass {   SimpleClass();     Code:        0: aload_0        1: invokespecial #1                  // Method java/lang/Object."<init>": ()V        4: return } 以16进制文件打开生成的class文件如下:


 
 

魔数(magic):

4bytes, 0xCAFEBABE 

版本(version):

包括主版本号和小版本号

小版本号(minor version):

2bytes,0x0000

主版本号(major version):

2bytes,0x0034

常量池:

常量池通过一个数组来保存各个常量,数组的大小-1就是常量池常量个数。针对不同类型的常量通过tag来表示。

常量池常量个数(constant pool count):

0x000D,转换为10进制就是13,

常量池(constant pool):

常量tag:

0x0A,表示一个CONSTANT_Methodref类型的常量

class_index:

0x0003,

name_and_type_index:

0x000A

常量tag:

0x07,表示一个CONSTANT_Class类型的常量

name_index:

0x000B,

常量tag:

0x07,表示一个CONSTANT_Class类型的常量

name_index:

0x000C

常量tag:

0x01, 表示一个CONSTANT_Utf8类型的常量

length:

0x0006, 表示字符串长度

bytes[length]:

0x3C696E69743E,表示字符串“<init>”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x0003,表示字符串长度

bytes[length]:

0x282956,表示字符串“()V”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x0004,表示字符串长度

bytes[length]:

0x436F6465,表示字符串“Code”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x000F,表示字符串长度

bytes[length]:

0x4C696E654E756D6265725461626C65,表示字符串“LineNumberTable”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x000A,表示字符串长度

bytes[length]:

0x536F7572636546696C65,表示字符串“SourceFile”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x0010,表示字符串长度

bytes[length]:

0x53696D706C65436C6173732E6A617661,表示字符串“SimpleClass.java”

常量tag:

0x0C,表示一个CONSTANT_NameAndType类型的常量

name_index:

0x0004,

descriptor_index:

0x0005,

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x000B, 表示字符串长度

bytes[length]:

0x53696D706C65436C617373,表示字符串“SimpleClass”

常量tag:

0x01,表示一个CONSTANT_Utf8类型的常量

length:

0x0010,表示字符串长度

bytes[length]:

0x6A6176612F6C616E672F4F626A656374,表示字符串“java/lang/Object”

访问控制修饰标志(access_flags):

0x0020

this_class:

0x0002

super_class:

0x0003

interfaces_count:

0x0000

interfaces[interfaces_count]:

fields_count:

0x0000

fields[fields_count]:

methods_count:

0x0001

methods[methods_count]:

方法:

access_flags:

0x0000

name_index:

0x0004

descriptor_index:

0x0005

attributes_count:

0x0001

attributes[attributes_count]:

attribute_name_index:

0x0006

attribute_length:

0x0000001D,表示29

info[attribute_length]:

0x00010001000000052AB70001B100000001000700000006000100000001

对info[attribute_length]的说明:Code_attribute

attribute_name_index:

就是上面对应的attribute_name_index:0x0006

attribute_length:

就是上面对应的attribute_length:0x0000001D,表示29

max_stack:

0x0001

max_locals:

0x0001

code_length:

0x00000005

code[code_length]:

0x2AB70001B1

从这里可以看出这个方法对应的代码指令就是:0x2AB70001B1,具体是些什么指令呢?

经过分析的结果就是:

0: aload_0
1: invokespecial #1
4: return

前面的数字表示对应的指令所占用的字节数,加起来正好5个字节。aload_0对应0x2A,invokespecial #1对应0xB70001,其中0xB7就表示invokespecial指令,return对应0xB1。这里主要就是调用了Object的无参构造方法,然后返回。

exception_table_length:

0x0000

{   u2 start_pc;

    u2 end_pc;

    u2 handler_pc;

    u2 catch_type;

} exception_table[exception_table_length]:

attributes_count:

0x0001

attributes[attributes_count]:

attribute_name_index:

0x0007

attribute_length:

0x00000006

info[attribute_length]:

0x000100000001

attributes_count:

0x0001

attributes[attributes_count]:

attribute_name_index:

0x0008

attribute_length:

0x00000002

info[attribute_length]:

0x0009

到这里整个字节码class文件就全部分析完了。

参考文章:Chapter 4. The class File Format,https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

猜你喜欢

转载自lobin.iteye.com/blog/2438472