【问题标题】:Generate code that implements JSR 308 "instanceof @MyAnotations" runtime check生成实现 JSR 308“instanceof @MyAnotations”运行时检查的代码
【发布时间】:2012-09-16 09:12:03
【问题描述】:

JSR 308 提议给 Java 添加类型注解。批准后,程序员将能够在当前允许 Java 类型的任何地方添加注释。这不仅包括方法/字段/本地/参数装饰,还包括构造函数调用、类型转换和最奇怪的 instanceof 检查。 Checker Framework 使用 JSR 308 实现类型限定符,例如对象类型上的 @NonNull 或字符串上的 @Regex

现在,Checkers 所做的就是静态分析您的代码。这就是所有编译时检查。没关系。但我想要的是一种可以在运行时进行检查的机制。你可以声明:

@Regex String p1 = "[a-z]+";
@Regex String p1 = "[a-z)+";    // compile time error from annotation processor

我也可以写:

if (x instanceof @Regex String) ...

但这与x instanceof String 没有什么不同,不执行运行时检查。 我需要一个编译时注释处理器运行时字节码操纵器,它可以让我在instanceof 检查上运行任意代码并返回一个布尔值。 Java可以做到这一点吗?

【问题讨论】:

    标签: java annotations code-generation bytecode-manipulation annotation-processing


    【解决方案1】:

    对于您的正则表达式示例,解决方案非常简单。我还提供了一些关于解决方案不是那么简单的案例的信息。

    如何实现运行时测试取决于类型系统是计算数据本身的属性,还是计算出处(数据的来源)的属性。这是Checker Framework manual的“Run-time tests and type refinement”部分的文本:

    某些类型系统支持 Checker Framework 的运行时测试 可用于细化条件范围内的类型,例如 if、 在断言语句等之后。

    类型系统是否支持这样的运行时测试取决于 类型系统是否正在计算数据本身的属性,或者 出处的属性(数据的来源)。一个例子 关于数据的属性是字符串是否是正则表达式。一个 关于出处的属性的示例是计量单位:有 无法查看数字的表示并确定是否 它旨在表示公里或英里。

    1) 对于 data 的属性,最简单的选择是避免使用 instanceof 测试,而是使用 Checker 框架附带的 tests,例如 isRegex

    例如,而不是

      if (x instanceof @Regex String) ...
    

      if (RegexUtil.isRegex(x)) ...
    

    你就完成了。

    如果您真的想使用instanceof 而不是isRegex,那么您需要破解编译器以将每个源代码出现的x instanceof @Regex String 转换为RegexUtil.isRegex(x)。你也可以通过字节码重写来做到这一点。

    2) 对于关于provenance 的属性,实施工作量要大得多。您必须在程序(包括对象和原语)中的每个数据的表示中添加一个出处位并更改每个操作(在您自己的程序和库中),以便除了对数据进行操作之外,它还可以适当地维护出处位。 DynComp 已经可以做到这一点,您可以在此基础上进行构建,它作为Daikon invariant detector 的一部分分发。

    【讨论】:

      【解决方案2】:

      是的,你可以。但它不是微不足道的,并且不受注释处理器可访问 API 的支持。可访问的注释处理器 API 仅限于生成新类,并且不允许修改现有字节码(即使在 JDK 8 中)。您可以在注解处理器级别强制转换为编译器特定的类,从而启用更多选项。但是您必须使用编译器内部 API 并为每个可用的编译器(JDT 和 JavaC)重写它。你可以看看项目 Lombok (http://projectlombok.org/),它做了非常相似的事情。遗憾的是,Lombok 尚不兼容 JDK8 的新型注释。

      【讨论】:

      • 你的意思是 Lombok 改变了书面代码?这与运行时字节码操作相比如何?维护每个编译器的代码可能会很昂贵。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-09
      • 1970-01-01
      • 2010-11-23
      • 2019-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多