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 | 
     | 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;”)
   
  附录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 | 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.       以上所有以上类型的一维数组。
                                                                                            于2010-12-19日