2.11 在classfile、method_info、field_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
constant_pool中的索引,constant_utf8_info類型。指定attribute名稱(“signature”)。
該attribute内容的位元組長度(2)。
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
constant_pool中的索引,constant_utf8_info類型。指定attribute名稱(“deprecated”)。
2.11.4 runtimevisibleannotations attribute
runtimevisibleannotations attribute記錄了目前類、方法、字段在源代碼中定義的、在運作時可見的annotation。java程式可以通過反射函數擷取這些annotation。一個attributes集合中隻能包含一項runtimevisibleannotations attribute,記錄所有運作時可見的annotation。
runtimevisibleannotations attribute
constant_pool中的索引,constant_utf8_info類型。指定attribute名稱(“runtimevisibleannotations”)。
該attribute内容的位元組長度。
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
constant_pool中的索引,constant_utf8_info類型。指定attribute名稱(“runtimeinvisibleannotations”)。
記錄所有運作時不可見的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
name
attributes
constantvalue attribute
methods
code attribute
stackmaptable attribute
linenumbertable attribute
localvariabletable attribute
localvariabletypetable attribute
exceptions attribute
runtimevisibleparameterannotations attribute
runtimeinvisibleparameterannotations attribute
annotationdefault attribute
innerclasses attribute
enclosingmethod attribute
sourcefile attribute
sourcedebugextension 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:
fieldtypesignature:
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;”)
附錄e:annotation結構和element_value結構
1. annotation結構
每一項annotation結構記錄一項使用者定義的annotation的值。如:
@test(id = 4, description = "description", usecase = @usecase())
@usecase()
void testexecute(int a) {
}
編譯器會為該方法生成兩項annotation。每項annotation指定了annotation的類型和鍵值對。
annotation結構
type_index
constant_pool中的索引。constant_utf8_info類型。以字段描述符(field descriptor)方式記錄目前結構表示的annotation類型。
num_element_value_pairs
記錄目前annotation中的鍵值對數。
element_value_pair
記錄每項annotation中的鍵值對表。
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結構
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鍵值對中的值。
constant_value_index
constant_pool中的索引,索引項必須是常量類型。當tag中的值為’b’ ‘c’ ‘d’ ‘f’ ‘i’ ‘j’ ‘s’ ‘z’ ‘s’時該項有效。
enum_const_value
當tag值為’e’時,該項有效。記錄枚舉類型值。
type_name_index
constant_pool中的索引,constant_utf8_info類型。記錄目前枚舉類型二進制名(binary name,好像就是類型名,以descriptor的形式表示)。
const_name_index
constant_pool中的索引,constant_utf8_info類型。記錄目前枚舉類型的值(枚舉類型内部成員字元串)。
class_info_index
constant_pool中的索引,constant_utf8_info類型。以descriptor記錄目前值所表達的class類型。當tag值為’c’時,該項有效。
annotation_value
當tag值為’@’時,該項有效。記錄目前annotation鍵值對中的值為内嵌的annotation。
array_value
當tag值為’[‘時,該項有效。記錄目前annotation鍵值對中的值為數組類型。
num_values
數組的長度。
values[num_values]
每一項記錄數組中的值。
注:從這個結構中,我們也可以得出annotation中可以設定的值類型:
1. 基本類型值(byte、char、double、float、int、long、short、boolean)
2. 字元串(string)
3. 枚舉(enum)
4. 類執行個體(class)
5. 嵌套注解類型(annotation)
6. 以上所有以上類型的一維數組。