Java注解的默认值是否编译成字节码? [英] Are Java annotation's default values compiled into bytecode?
问题描述
我尝试为 Java 字节码实现几个静态分析.他们尝试计算某个方法是否具有特定属性,例如是工厂方法.因为这些分析很难测试,所以我决定写一些 Java 代码并直接用正确的属性注释方法.运行分析后,很容易自动检查计算和注释的属性是否相同.
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.
我的注释:
@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".但是当我没有明确地将枚举值传递给注解时,它不会被编译成字节码.
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.
字节码:
#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 会构造一个您可以检索的注释实例.此实例将使用 default
值初始化,该值位于注释本身的 .class
文件中.这表示为 AnnotationDefault
属性
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 节),即那些代表注释类型的元素.AnnotationDefault
属性记录了该元素所代表的默认值method_info
结构.
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 themethod_info
structure.
每个 method_info
结构代表一个注解的元素type 最多可以包含一个 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.
您最终将调用注释实例的 value()
方法(或您定义的任何其他方法),它会返回该值.
You'll eventually invoke the annotation instance's value()
method (or whatever other method you defined) and it will return that value.
这篇关于Java注解的默认值是否编译成字节码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!