Java类文件解析

首先声明,本文只是使用类文件的平常情况进行说明,对一些特殊情况不深入研究.(比如:int常量多大才会进入常量池而不是嵌入到代码中,为什么接口中的方法被实现后不出现在常量池中等等).首先,对类文件的格式做个总括;然后分别对每个部分进行详细说明;最后使用一个简单的类文件作为例子进行说明.

 

类文件的信息如以下格式排列:

 

Magic Num->minor number->major number->constant_pool_count->constant_pool->access_flags->this_class->super_class->interfaces_count->interfaces->fields_count->fields->methods_count->methods->attributes_count->attributes

Magic Num:占4个字节,”CAFE BABE”代表class文件符合JVM格式.

minor number和major number:它们组合表示语言的版本.如”0034”对应”52.0”,前两个字节是minor number,代表小数点后的数字;后两个字节是major number,代表小数点前的数字.

constant_pool_count:2个字节,代表常量池的长度 + 1.

这里需要说明一下,constant_pool,interfaces,fields,methods和attributes这几个区域阅读步骤如下:

1)查看X_count的值(除了常量池,其他值直接代表长度),确定区域的长度,每个区域都有对应长度的信息.如constant_pool_count = 20,那么常量池具有19个常量.

2)每个信息都有自己的类型,信息的开头都是关于类型的值.通过信息的开头可以分割开各个信息.

3)阅读每个分割的信息

constant_pool:长度不限,包含constant_pool_count - 1个常量信息.以下列举常用的常量

常量类型

常量格式

说明

CONSTANT_Utf8_info

tag(01)  length  content

每种常量都具有一个tag;说明常量的类型.length是常量的长度,2个字节;content是utf8常量的内容.每一个字节代表一个utf8字符.

 

CONSTANT_Integer_info

tag(03)  bytes

bytes是int常量的值,占4个字节

CONSTANT_Float_info

tag(04)  bytes

bytes是float常量的值,占4个字节

CONSTANT_Long_info

tag(05)  bytes

bytes是long常量的值,占8个字节

CONSTANT_Double_info

tag(06)  bytes

bytes是double常量的值,占8个字节

CONSTANT_Class_info

tag(07)  index

index指向类全限定名的tag

CONSTANT_String_info

tag(08)  index

index指向字符串字面量的tag

CONSTANT_Fieldref_info

tag(09)  index0  index1

index0指向声明该字段的Class_info,index1指向该字段的NameAndType_info

CONSTANT_Methodref_info

tag(10)  index0  index1

index0指向声明该方法的Class_info的tag, index1指向该方法的NameAndType_info的tag

CONSTANT_NameAndType_info

tag(12)  index0  index1

index0指向name的tag,index1指向type的tag

备注:

1)Class_info,String_info,Fieldref_info,Methodref_info和NameAndType_info可以看作是对象,index对应属性.Utf8_info,Integer_info,Float_info, Long_info,Double_info可以看作是基本类型.

2)NameAndType的type的utf8值在Fieldref和Methodref中具有不同的表示.

Methodred中的type代表方法的说明,具有两个部分和三种类型,分别如下:

void m() ()V //空类型,构造方法的返回值也为void

String toString() ()Ljava/lang/String //引用类型,L代表引用

long(int[] arr1,int num,long length) ([IIJ)J //基本类型,I代表整数,J代表长整数.数组需要在前面加”[”.

所有基本类型的字母在fields中展示.

Fieldref中的type代表常量的类型的类全限定名.

3)tag默认是1个字节,index默认是2个字节

access_flags:2个字节,代表类信息.相当于bitmap,每一位代表一项信息,信息如下:

位置名称

位置

作用

ACC_PUBLIC

0x0001

该类是否是public类

ACC_FINAL

0x0010

该类是否是final类

ACC_SUPER

0x0020

编译器会自动设置为true

ACC_INTERFACE

0x0200

该类是否是接口

ACC_ABSTRACT

0x0400

该类是否是接口或者抽象类

ACC_SYNTHETIC

0x1000

编译器自动生成

ACC_ANNOTATION

0x2000

该类是否是注解

ACC_ENUM

0x4000

该类是否是枚举类

 

this_class:2个字节,指向该类在常量池中的Class_Info

super_class:2个字节,指向该类的父类在常量池中的Class_Info

interfaces_count:2个字节,该类中实现的接口数量

interfaces:2个字节,包含interfaces_count个接口信息,每个接口信息直指向常量池中该接口的Class_Info的偏移地址

fields_count:2个字节,该类中属性,以及该类方法调用过的其他类的属性数量

fields:通常为6个字节,包含fields_count个属性信息,每个属性包含以下内容:

  access_flags:2个字节,代表属性修饰信息,相当于bitmap,每一位代表一项信息,信息如下:

位置名称

位置

ACC_PUBLIC

0x0001

ACC_PRIVATE

0x0002

ACC_PROTECTED

0x0004

ACC_STATIC

0x0008

ACC_FINAL

0x0010

ACC_VOLATILE

0x0040

ACC_TRANSIENT

0x0080

ACC_SYNTHETIC

0x1000

ACC_ENUM

0x4000

  name_index:2个字节,属性名在常量池中的偏移地址

  descriptor_index:2个字节,属性类型符号在常量池中的偏移地址,所有属性类型如下所示

符号

属性类型

B

byte类型

C

char类型

D

double类型

F

float类型

I

int类型

J

long类型

S

short类型

Z

boolean类型

V

void类型

L

Object类型.另外,如果是继承Object的需要加上类全限定名

[

一维数组,需要放在其他类型前面

[[[...

多维数组

注意:常量池中只会出现该类中使用过的属性类型对应的符号

另外,attributes_count和attributes不常用,这里不做列举.

 

methods_count:2个字节,该类中方法以及该类方法中调用过的其他类的方法数量

methods:通常字节数不固定,包含methods_count个方法信息,每个方法包含以下内容:

  access_flags:2个字节,代表方法修饰信息,相当于bitmap,每一位代表一项信息,常用的信息如下:

位置名称

位置

ACC_PUBLIC

0x0001

ACC_PRIVATE

0x0002

ACC_PROTECTED

0x0004

ACC_STATIC

0x0008

ACC_FINAL

0x0010

ACC_SYNCHRONIZED

0x0020

ACC_NATIVE

0x0100

ACC_ABSTRACT

0x0400

ACC_SYNTHETIC

0x1000

  name_index:2个字节,方法名在常量池中的偏移地址

  descriptor_index:2个字节,该类对应的NameAndType在常量池中的偏移地址

  attributes_count:2个字节,代表该方法中attributes的数量
  attribute属性,方法都可能存在,可以认为是额外信息.它也可以在类文件中独立存在,通常保存源文件名.

  attributes:方法中的attribute,通常包含一个Code结构(一种attribute结构),它代表方法中的代码,Code结构如下:

  attribute_name_index:2个字节,代表该attribute名字在常量池中的偏移地址.

  attribute_length:4个字节,该attribute的长度

  max_stack:2个字节,暂且不明功能

  max_local:2个字节,方法中局部变量数量

  code_length:4个字节,代码长度

  code:code_length个字节,存储方法中代码的字节码

  exception_table_length:2个字节,异常表的长度

  exception_table:exception_table_length个字节,存储方法中的异常

attributes_count:2个字节,Code中的attribute数量.通常包含LineNumberTable和LocalVariableTable,暂且不深入

attributes:包含attributes_count个attribute

 

最后是class文件的attribtues,结构与上面所说的相似,暂且不深入.

 

上一篇:int main (int argc, const char * argv[0]) 中参数的含义;指针数组和数组指针


下一篇:Java设计模式-22、状态模式-处理对象的多种状态及其相互转换