字节码Signature属性

位于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 {
    private E element;
    public E getMiddle(E[] a) {
        int index = a.length / 2;
        return a[index];
    }
}
public class com.enjoy.wz.generics.ArrayAlg 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."":()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               
   #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;
  #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               Ljava/lang/Object;
  #26 = Utf8               SourceFile
  #27 = Utf8               ArrayAlg.java
  #28 = NameAndType        #8:#9          // "":()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."":()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;

  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;
            0       9     1     a   [TE;
    Signature: #24                          // ([TE;)TE;
}
Signature: #25                          // 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;
            0       9     1     a   [TE;

LocalVariableTypeTable与 LocalVariableTable基本一样,只不过添加了泛型信息。

2)关于方法的Signature

Signature: #24                          // ([TE;)TE;

3)关于类的Signature

Signature: #25                          // Ljava/lang/Object;

你可能感兴趣的:(字节码Signature属性)