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

Java字节码(.class资料)格式详解(三)

2012-10-15 
Java字节码(.class文件)格式详解(三)2.11 在ClassFile、method_info、field_info中同时存在的Attribute2.11.

Java字节码(.class文件)格式详解(三)

2.11 ClassFilemethod_infofield_info中同时存在的Attribute

2.11.1 Synthetic Attribute

Synthetic Attribute用于指示当前类、接口、方法或字段由编译器生成,而不在源代码中存在(不包含类初始函数和实例初始函数)。相同的功能还有一种方式就是在类、接口、方法或字段的访问权限中设置ACC_SYNTHETIC标记。

?

Synthetic Attribute由JDK1.1中引入,以支持内嵌类和接口(nested classes and interfaces)。但是以我现在所知,这些功能都是可以通过ACC_SYNTHETIC标记来表达的,为什么还需要存在Synthetic Attribute呢?在什么样的情况下会生成Synthetic Attribute项呢?我还没有找到,需要继续研究。

Synthetic Attribute

type

descriptor

remark

u2

attribute_name_index

constant_pool中的索引,CONSTANT_Utf8_info类型。指定Attribute名称(“Synthetic”)。

u4

attribute_length

该Attribute内容的字节长度(0)。

?

2.11.2 Signature Attribute

Signature Attribute

type

descriptor

remark

u2

attribute_name_index

constant_pool中的索引,CONSTANT_Utf8_info类型。指定Attribute名称(“Signature”)。

u4

attribute_length

该Attribute内容的字节长度(2)。

u2

signature_index

constant_pool中的索引,CONSTANT_Utf8_info类型。记录当前类型的签名(类签名、字段签名、方法签名)。

JVM规范中没有指定什么情况下需要生成Signature Attribute。但是从Signature的目的是用于泛型类型,可以推测Signature Attribute存在于当前Signature Attribute所在类型是泛型(泛型类、泛型方法、泛型字段)的时候。它和field_info、method_info、this_class一起对应于局部变量中的LocalVariableTable Attribute和LocalVariableTypeTable Attribute,他们同时都有descriptor版本和signature版本。

?

2.11.3 Deprecated Attribute

Deprecated Attribute指示当前类、方法、字段已经过时了,一些工具,如编译器可以根据该Attribute提示用户他们使用的类、方法、字段已经过时了,最好使用最新版本的类、方法、字段。

Deprecated Attribute

type

descriptor

remark

u2

attribute_name_index

constant_pool中的索引,CONSTANT_Utf8_info类型。指定Attribute名称(“Deprecated”)。

u4

attribute_length

该Attribute内容的字节长度(0)。

?

2.11.4 RuntimeVisibleAnnotations Attribute

RuntimeVisibleAnnotations Attribute记录了当前类、方法、字段在源代码中定义的、在运行时可见的Annotation。Java程序可以通过反射函数获取这些Annotation。一个attributes集合中只能包含一项RuntimeVisibleAnnotations Attribute,记录所有运行时可见的Annotation。

RuntimeVisibleAnnotations Attribute

type

descriptor

remark

u2

attribute_name_index

constant_pool中的索引,CONSTANT_Utf8_info类型。指定Attribute名称(“RuntimeVisibleAnnotations”)。

u4

attribute_length

该Attribute内容的字节长度。

u2

num_annotations

annotations集合长度。

annotation

annotations[num_annotations]

记录所有运行时可见的annotation的集合。annotation类型详见附录E

?

2.11.5 RuntimeInvisibleParameterAnotations Attribute

RuntimeInvisibleAnnotations Attribute记录了当前类、方法、字段在源代码中定义的、在运行时不可见的Annotation。默认情况下,这些Annotation是不可被Java提供的反射函数获取的,需要通过和实现相关的机制来获取这些Annotation。一个attributes集合中只能包含一项RuntimeInvisibleAnnotations Attribute,记录所有运行时不可见的Annotation。

RuntimeInvisibleAnnotations Attribute

type

descriptor

remark

u2

attribute_name_index

constant_pool中的索引,CONSTANT_Utf8_info类型。指定Attribute名称(“RuntimeInvisibleAnnotations”)。

u4

attribute_length

该Attribute内容的字节长度。

u2

num_annotations

annotations集合长度。

annotation

annotations[num_annotations]

记录所有运行时不可见的annotation的集合。annotation类型详见附录E

?


?

总体格式

magic(0xCAFEBABE)

version(major.minor)

constant pool

CONSTANT_Utf8_info(1)

CONSTANT_Integer_info(3)

CONSTANT_Float_info(4)

CONSTANT_Long_info(5)

CONSTANT_Double_info(6)

CONSTANT_Class_info(7)

CONSTANT_String_info(8)

CONSTANT_Fieldref_info(9)

CONSTANT_Methodref_info(10)

CONSTANT_InterfaceMethodref_info(11)

CONSTANT_NameAndType_info(12)

access_flags

this_class

super_class

interfaces

fields

access_flags

name

descriptor

attributes

ConstantValue Attribute

Synthetic Attribute

Signature Attribute

Deprecated Attribute

RuntimeVisibleAnnotations Attribute

RuntimeInvisibleAnnotations Attribute

?

methods

access_flags

name

descriptor

attributes

Code Attribute

StackMapTable Attribute

LineNumberTable Attribute

LocalVariableTable Attribute

LocalVariableTypeTable Attribute

?

Exceptions Attribute

RuntimeVisibleParameterAnnotations Attribute

RuntimeInvisibleParameterAnnotations Attribute

AnnotationDefault Attribute

Synthetic Attribute

Signature Attribute

Deprecated Attribute

RuntimeVisibleAnnotations Attribute

RuntimeInvisibleAnnotations Attribute

?

attributes

InnerClasses Attribute

EnclosingMethod Attribute

SourceFile Attribute

SourceDebugExtension Attribute

Synthetic Attribute

Signature Attribute

Deprecated Attribute

RuntimeVisibleAnnotations Attribute

RuntimeInvisibleAnnotations Attribute


?

附件A Java字节码中的类和接口名

在Java字节码中类和接口名主要表现以下几点:

1. 类和接口名都是以全限定名的方式存放(包名加类或接口名)。

2. 在源代码中的点分隔符”.”在字节码中以斜杠”/”代替。如:“java.lang.Object”-> “java/lang/Object

3. 数组类型名做了特殊处理。如:“int[][]”-> “[[I”、“Thread[]”->“[Ljava/lang/Thread”。详见附录B:Java字节码中的数组类型名

?

?

附件B Java字节码中的数组类型名

?

在Java中,数组被认为是类,因而它也有对应的类名表示,而Java字节码为数组名指定了特定的格式:

1. 所有数组名都以“[”开头,n维数组有n个“[”。

2. 对引用类型的数组,在“[”后加“L后加引用类型的全限定名。

3. 对基本类型,在“[”后加基本类型的对应字符

基本类型对应字符表

基本类型

对应字符

byte

B

char

C

double

D

float

F

int

I

long

J

short

S

boolean

Z

?

附件C 描述符(Descriptor

描述符(Descriptor)定义了字段或方法的类型(A descriptor is a string representing the type of a field or method.这段描述感觉不怎么精确)。它存放在constant pool中的CONSTANT_Utf8_info类型项中。

1. 字段描述符(Field Descriptor

字段描述符是定义了字段、局部变量、参数等类型的字符串。即附录A中的类或接口名。

语法定义:

FieldDescrptor :

FieldType

?

BaseType : B、C、D、F、I、J、S、Z(参考附录B中的基本类型对应字符表)

ObjectType : LfullClassName;

ArrayType : [+BaseType | [+ObjectType

FieldType : BaseType | ObjectType | ArrayType

如:[[D -> double[][]、[Ljava/lang/Thread; -> Thread[]、I->int、Ljava/lang/Object; -> Object

?

2. 方法描述符(Method Descriptor

方法描述符是定义了方法参数、方法返回等信息的字符串。

语法定义:

MethodDescriptor:

(ParameterDescriptor*)ReturnDescriptor

?

ParameterDescriptor : FieldType

ReturnDescriptor : FieldType | VoidDescriptor

VoidDescriptor : V

如:void method(int i, Object obj)-> (ILjava/lang/Object;)V

Object getValue()-> ( )Ljava/lang/Object;

Object mymethod(int i, double d, Object o) -> (IDLjava/lang/Object;)Ljava/lang/Object;

?

附件D 签名(Signature

?

签名(Signature)定义了类、字段或方法的泛型类型信息(A signature is a string representing the generic type of a field or method, or generic type information for a class declaration. 这段描述感觉不怎么精确)。它也存放在constant pool中的CONSTANT_Utf8_info类型项中。

它存在于Signature Attribute中,只有包含泛型的类、字段、方法才会产生Signature Attribute

签名信息并不是给JVM用的,而是用于编译、调试、反射。

1. 类签名

语法定义:

ClassSignature:

FormalTypeParametersopt SuperclassSignature SuperinterfaceSignature*

FormalTypeParameters:

<FormalTypeParameter+>

FormalTypeParameter:

Identifier ClassBound InterfaceBound*

ClassBound:

: FieldTypeSignatureopt

InterfaceBound:

: FieldTypeSignature

SuperclassSignature:

ClassTypeSignature

SuperinterfaceSignature:

ClassTypeSignature

FieldTypeSignature:

ClassTypeSignature

ArrayTypeSignature

TypeVariableSignature

ClassTypeSignature:

L PackageSpecifier* SimpleClassTypeSignature

ClassTypeSignatureSuffix* ;

PackageSpecifier:

Identifier / PackageSpecifier*

SimpleClassTypeSignature:

Identifier TypeArgumentsopt

ClassTypeSignatureSuffix:

. SimpleClassTypeSignature

TypeVariableSignature:

T Identifier ;

TypeArguments:

<TypeArgument+>

TypeArgument:

WildcardIndicatoropt FieldTypeSignature

*

WildcardIndicator:

+

-

ArrayTypeSignature:

[TypeSignature

TypeSignature:

FieldTypeSignature

BaseType

以上定义没有看懂??例子如:

对class MyClass<T> { } 定义的类,产生如下的签名:

<T:Ljava/lang/Object;>Ljava/lang/Object;

而对以下类定义:

class MyClass<T1, T2> extends ClassFileParser implements IndexParser {

}

则产生如下签名:

<T1:Ljava/lang/Object;T2:Ljava/lang/Object;>Lorg/levin/classfilereader/ClassFileParser;Lorg/levin/classfilereader/IndexParser;

2. 字段签名

语法定义如上,没能看懂。从Tomcat代码中的Digester.class文件中可以解析得到如下的例子:

Ljava/util/HashMap<Ljava/lang/String;Ljava/util/Stack<Ljava/lang/String;>;>;(对应的descriptor:“Ljava/util/HashMap;”)

Ljava/util/Stack<Ljava/lang/Object;>;(对应的descriptor:“Ljava/util/Stack;”)

3. 方法签名

语法定义:

MethodTypeSignature:

FormalTypeParametersopt (TypeSignature*) ReturnType

ThrowsSignature*

ReturnType:

TypeSignature

VoidDescriptor

ThrowsSignature:

^ClassTypeSignature

^TypeVariableSignature

也没能看懂。同样从Tomcat代码中的Digester.class文件中可以解析得到如下例子:

(Ljava/lang/String;Ljava/lang/Class<*>;Ljava/lang/String;)V(对应descriptor:“(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;)V”)

(Ljava/lang/String;Ljava/lang/Class<*>;Ljava/lang/String;Z)V(对应descriptor:“(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Z)V”)

()Ljava/util/Map<Ljava/lang/String;Ljava/net/URL;>;(对应descriptor:“()Ljava/util/Map;”)

?

附录Eannotation结构和element_value结构

?

1. annotation结构

每一项annotation结构记录一项用户定义的annotation的值。如:

@Test(id = 4, description = "description", useCase = @UseCase())

@UseCase()

void testExecute(int a) {

}

编译器会为该方法生成两项annotation。每项annotation指定了annotation的类型和键值对。

annotation结构

type

descriptor

remark

u2

type_index

constant_pool中的索引。CONSTANT_Utf8_info类型。以字段描述符(field descriptor)方式记录当前结构表示的annotation类型。

u2

num_element_value_pairs

记录当前annotation中的键值对数。

element_value_pair

记录每项annotation中的键值对表。

u2

element_name_index

constant_pool中的索引。CONSTANT_Utf8_info类型。记录当前annotation中当前键值对的键名。如上例的“id”、“description”等。

element_value

value

当前annotation中当前键值对的值。详见element_value结构一节。

element_value_pairs[num_element_value_pairs]

?

?

2. element_value结构

element_value结构记录了所有annotation类型的键值对中的值。它是一个联合类型,可以表示多种类型的值。

element_value结构

type

descriptor

remark

u1

tag

tag记录了当前annotation键值对中值的类型,’B’、’C’、’D’、’F’、’I’、’J’、’S’、’Z’表示基本类型(见附录B中的基本类型对应表);其他的合法值有:

’s’ -> String

‘e’ -> enum constant

‘c’ -> class

‘@’ -> annotation type

‘[‘ -> array

value 联合体类型(union)

union类型,记录当前annotaion键值对中的值。

u2

constant_value_index

constant_pool中的索引,索引项必须是常量类型。当tag中的值为’B’ ‘C’ ‘D’ ‘F’ ‘I’ ‘J’ ‘S’ ‘Z’ ‘s’时该项有效。

enum_const_value

当tag值为’e’时,该项有效。记录枚举类型值。

u2

type_name_index

constant_pool中的索引,CONSTANT_Utf8_info类型。记录当前枚举类型二进制名(binary name,好像就是类型名,以descriptor的形式表示)。

u2

const_name_index

constant_pool中的索引,CONSTANT_Utf8_info类型。记录当前枚举类型的值(枚举类型内部成员字符串)。

enum_const_value

u2

class_info_index

constant_pool中的索引,CONSTANT_Utf8_info类型。以descriptor记录当前值所表达的Class类型。当tag值为’c’时,该项有效。

annotation

annotation_value

当tag值为’@’时,该项有效。记录当前annotation键值对中的值为内嵌的annotation。

array_value

当tag值为’[‘时,该项有效。记录当前annotation键值对中的值为数组类型。

u2

num_values

数组的长度。

element_value

values[num_values]

每一项记录数组中的值。

array_value

value

?

注:从这个结构中,我们也可以得出annotation中可以设置的值类型:

1. 基本类型值(byte、char、double、float、int、long、short、boolean)

2. 字符串(String)

3. 枚举(enum)

4. 类实例(Class)

5. 嵌套注解类型(annotation)

6. 以上所有以上类型的一维数组。

热点排行