位于ClassFile、field_info或method_info结构的属性表中。任何类、接口、构造器方法或字段的声明如果包含了类型变量(type variable)或参数化类型,则Signature属性会为它记录泛型签名信息。
Signature_attribute {
u2 attribute_name_index; //指向常量池的"Signature"
u4 attribute_length; // 为2
u2 signature_index; //指向常量池的类签名、方法类型前面、字段类型签名
}
签名有助于实现反射、调试以及编译,现在Java的反射API能够获取到泛型类型,最终的数据来源就是这个属性。
1.Signature文法
1)JavaTypeSignature表示引用类型或原始类型
JavaTypeSignature:
ReferenceTypeSignature
BaseType
BaseType:
(one of)
B C D F I J S Z
ReferenceTypeSignature:
ClassTypeSignature
TypeVariableSignature
ArrayTypeSignature
ClassTypeSignature:
L [PackageSpecifier] SimpleClassTypeSignature {ClassTypeSignatureSuffix} ;
PackageSpecifier:
Identifier / {PackageSpecifier}
SimpleClassTypeSignature:
Identifier [TypeArguments]
TypeArguments:
< TypeArgument {TypeArgument} >
TypeArgument:
[WildcardIndicator] ReferenceTypeSignature
*
WildcardIndicator:
+
-
ClassTypeSignatureSuffix:
. SimpleClassTypeSignature
TypeVariableSignature:
T Identifier ;
ArrayTypeSignature:
[ JavaTypeSignature
2)ClassSignature表示类声明的类型信息
ClassSignature:
[TypeParameters] SuperclassSignature {SuperinterfaceSignature}
TypeParameters:
< TypeParameter {TypeParameter} >
TypeParameter:
Identifier ClassBound {InterfaceBound}
ClassBound:
: [ReferenceTypeSignature]
InterfaceBound:
: ReferenceTypeSignature
SuperclassSignature:
ClassTypeSignature
SuperinterfaceSignature:
ClassTypeSignature
3)MethodSignature 方法声明的类型信息
MethodSignature:
[TypeParameters] ( {JavaTypeSignature} ) Result {ThrowsSignature}
Result:
JavaTypeSignature
VoidDescriptor
ThrowsSignature:
^ ClassTypeSignature
^ TypeVariableSignature
VoidDescriptor:
V
4)FieldSignature 字段声明、形式参数声明或局部变量声明
FieldSignature:
ReferenceTypeSignature
2.示例
public class ArrayAlg<E> {
private E element;
public E getMiddle(E[] a) {
int index = a.length / 2;
return a[index];
}
}
public class com.enjoy.wz.generics.ArrayAlg<E extends java.lang.Object> extends java.lang.Object
minor version: 0
major version: 52
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #2 // com/enjoy/wz/generics/ArrayAlg
super_class: #3 // java/lang/Object
interfaces: 0, fields: 1, methods: 2, attributes: 2
Constant pool:
#1 = Methodref #3.#28 // java/lang/Object."<init>":()V
#2 = Class #29 // com/enjoy/wz/generics/ArrayAlg
#3 = Class #30 // java/lang/Object
#4 = Utf8 element
#5 = Utf8 Ljava/lang/Object;
#6 = Utf8 Signature
#7 = Utf8 TE;
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 LocalVariableTable
#13 = Utf8 this
#14 = Utf8 Lcom/enjoy/wz/generics/ArrayAlg;
#15 = Utf8 LocalVariableTypeTable
#16 = Utf8 Lcom/enjoy/wz/generics/ArrayAlg<TE;>;
#17 = Utf8 getMiddle
#18 = Utf8 ([Ljava/lang/Object;)Ljava/lang/Object;
#19 = Utf8 a
#20 = Utf8 [Ljava/lang/Object;
#21 = Utf8 index
#22 = Utf8 I
#23 = Utf8 [TE;
#24 = Utf8 ([TE;)TE;
#25 = Utf8 <E:Ljava/lang/Object;>Ljava/lang/Object;
#26 = Utf8 SourceFile
#27 = Utf8 ArrayAlg.java
#28 = NameAndType #8:#9 // "<init>":()V
#29 = Utf8 com/enjoy/wz/generics/ArrayAlg
#30 = Utf8 java/lang/Object
{
public com.enjoy.wz.generics.ArrayAlg();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 10: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/enjoy/wz/generics/ArrayAlg;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 5 0 this Lcom/enjoy/wz/generics/ArrayAlg<TE;>;
public E getMiddle(E[]);
descriptor: ([Ljava/lang/Object;)Ljava/lang/Object;
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=3, args_size=2
0: aload_1
1: arraylength
2: iconst_2
3: idiv
4: istore_2
5: aload_1
6: iload_2
7: aaload
8: areturn
LineNumberTable:
line 13: 0
line 14: 5
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/enjoy/wz/generics/ArrayAlg;
0 9 1 a [Ljava/lang/Object;
5 4 2 index I
LocalVariableTypeTable:
Start Length Slot Name Signature
0 9 0 this Lcom/enjoy/wz/generics/ArrayAlg<TE;>;
0 9 1 a [TE;
Signature: #24 // ([TE;)TE;
}
Signature: #25 // <E:Ljava/lang/Object;>Ljava/lang/Object;
SourceFile: "ArrayAlg.java"
1)关于局部变量的Signature
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/enjoy/wz/generics/ArrayAlg;
0 9 1 a [Ljava/lang/Object;
5 4 2 index I
LocalVariableTypeTable:
Start Length Slot Name Signature
0 9 0 this Lcom/enjoy/wz/generics/ArrayAlg<TE;>;
0 9 1 a [TE;
LocalVariableTypeTable与 LocalVariableTable基本一样,只不过添加了泛型信息。
2)关于方法的Signature
Signature: #24 // ([TE;)TE;
3)关于类的Signature
Signature: #25 // <E:Ljava/lang/Object;>Ljava/lang/Object;