问题描述
我尝试实施Java字节code几个静态分析。他们试图计算如果某个方法有一个特定的属性,例如是一个工厂方法。由于这些分析是难以测试,我决定写一些Java code和直接与正确的属性注释的方法。运行分析后,这是很容易自动检查是否有计算和注释的属性是一样的。
I try to implement several static analyses for Java bytecode. They try to compute if a certain method has a specific property, e.g. is a factory method. Because these analyses are difficult to test, I decided to write some Java code and annotate the methods directly with the correct property. After running the analysis, it is quite easy to check automatically whether the computed and the annotated property is the same.
MyAnnotation:
MyAnnotation:
@Retention(RUNTIME)
@Target(METHOD)
public @interface FactoryMethodProperty {
FactoryMethodKeys value() default FactoryMethodKeys.NonFactoryMethod;
}
例测试code:
Example test code:
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();
}
}
由于大部分在我的测试code中的方法是没有工厂的方法,我的默认设置为枚举值FactoryMethodKeys.NonFactoryMethod。但是,当我没有明确的枚举值传递给注解,它不是编译成字节code。
Because most of the methods in my test code are no factory methods, I set the default to the enum value "FactoryMethodKeys.NonFactoryMethod". But when I don't explicitly pass the enum value to the annotation, it is not compiled to the bytecode.
字节code:
#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, locals=0, 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
}
我是怎么了?为什么默认值完全忽略了?
What did I wrong? Why is the default value completely ignored?
推荐答案
它并不需要在那里。在运行时,JVM构造了一个注释实例,你可以检索。这个实例将是在的.class
文件进行注释本身默认
值进行初始化。这是psented作为的
It doesn't need to be there. At runtime, the JVM constructs an annotation instance that you can retrieve. This instance will be initialized with the default
value which is in the .class
file for the annotation itself. That's represented as an AnnotationDefault
attribute
的 AnnotationDefault
属性是在一个可变长度的属性
某些属性 method_info
结构(§4.6),即表
注释类型的那些重新presenting元素。在 AnnotationDefault
属性记录由psented重新$ P $元素的默认值
method_info
结构。
每个 method_info
结构重新presenting注释的元素
类型可能包含至多一个 AnnotationDefault
属性。 在Java
虚拟机必须提供这些默认值,因此它可以是
通过适当的反射API的应用
Each method_info
structure representing an element of an annotation type may contain at most one AnnotationDefault
attribute. The Java Virtual Machine must make this default value available so it can be applied by appropriate reflective APIs.
您最终会调用注释实例的值()
方法(或任何其他方法,你定义的),它会返回一个值。
You'll eventually invoke the annotation instance's value()
method (or whatever other method you defined) and it will return that value.
这篇关于是Java注释的默认值编译成字节code?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!