Java注解的默认值是否编译成字节码? [英] Are Java annotation's default values compiled into bytecode?

查看:25
本文介绍了Java注解的默认值是否编译成字节码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试为 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 certain method_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.

每个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆