我尝试为
Java字节码实现几个静态分析.他们尝试计算某个方法是否具有特定的属性,例如是一种工厂方法.因为这些分析很难测试,所以我决定写一些Java代码,并用正确的属性直接注释方法.运行分析后,自动检查计算的和注释的属性是否相同是很容易的.
MyAnnotation:
@Retention(RUNTIME) @Target(METHOD) public @interface FactoryMethodProperty { FactoryMethodKeys value() default FactoryMethodKeys.NonFactoryMethod; }
示例测试代码:
public class PublicFactoryMethod { private PublicFactoryMethod(){ // I'm private } @FactoryMethodProperty public static void newInstanceAfterOtherConstructorCall(){ new TransFacoryMethod(); new PublicFactoryMethod(); } @FactoryMethodProperty(FactoryMethodKeys.IsFactoryMethod) public static PublicFactoryMethod newInstance(){ return new PublicFactoryMethod(); } }
因为我的测试代码中的大多数方法都不是工厂方法,所以我将默认值设置为枚举值“FactoryMethodKeys.NonFactoryMethod”.但是,当我没有将枚举值显式传递给注释时,它不会被编译为字节码.
字节码:
#23 = Utf8 value #24 = Utf8 Lorg/opalj/fpa/test/annotations/FactoryMethodKeys; #25 = Utf8 IsFactoryMethod { public static void newInstanceAfterOtherConstructorCall(); descriptor: ()V flags: ACC_PUBLIC,ACC_STATIC RuntimeVisibleAnnotations: 0: #16() Code: stack=1,locals=0,args_size=0 0: new #17 // class factoryMethodTest/TransFacoryMethod 3: invokespecial #19 // Method factoryMethodTest/TransFacoryMethod."<init>":()V 6: new #1 // class factoryMethodTest/PublicFactoryMethod 9: invokespecial #20 // Method "<init>":()V 12: return LineNumberTable: line 49: 0 line 50: 6 line 51: 12 LocalVariableTable: Start Length Slot Name Signature public static factoryMethodTest.PublicFactoryMethod newInstance(); descriptor: ()LfactoryMethodTest/PublicFactoryMethod; flags: ACC_PUBLIC,ACC_STATIC RuntimeVisibleAnnotations: 0: #16(#23=e#24.#25) Code: stack=2,args_size=0 0: new #1 // class factoryMethodTest/PublicFactoryMethod 3: dup 4: invokespecial #20 // Method "<init>":()V 7: areturn LineNumberTable: line 55: 0 LocalVariableTable: Start Length Slot Name Signature }
我错了什么?为什么默认值完全被忽略?
解决方法
它不需要在那里在运行时,JVM构造一个可以检索的注释实例.该实例将使用默认值进行初始化,该默认值在.class文件中,用于注释本身.这表示为
AnnotationDefault
attribute
The @H_502_24@AnnotationDefault attribute is a variable-length attribute in the
attributes table of certain @H_502_24@method_info structures (§4.6),namely
those representing elements of annotation types. The@H_502_24@AnnotationDefault
attribute records the default value for the element represented by the
@H_502_24@method_info structure.Each @H_502_24@method_info structure representing an element of an annotation
type may contain at most one @H_502_24@AnnotationDefault attribute. The Java
Virtual Machine must make this default value available so it can be
applied by appropriate reflective APIs.