我尝试为
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
AnnotationDefault
attribute is a variable-length attribute in the
attributes table of certainmethod_info
structures (§4.6),namely
those representing elements of annotation types. TheAnnotationDefault
attribute records the default value for the element represented by the
method_info
structure.Each
method_info
structure representing an element of an annotation
type may contain at most oneAnnotationDefault
attribute. The Java
Virtual Machine must make this default value available so it can be
applied by appropriate reflective APIs.