Skip to content

JEP 119: javax.lang.model Implementation Backed by Core Reflection | 由核心反射支持的 javax.lang.model 实现

摘要

提供一个基于核心反射(core reflection)而不是 javac 的 javax.lang.model.* API 的实现。换句话说,提供一种替代 API 来访问和处理有关已加载类的反射信息。

目标

提供一个统一的 API,用于查看关于类型及其成员的编译时和运行时反射信息。降低对与注解相关的语言特性进行实验的门槛。

动机

核心反射 API 存在各种设计限制;有关详情,请参阅 Mirrors: Design Principles for Meta-level Facilities of Object-Oriented Programming Languages

javax.lang.model.* API 在 javac 中用于其注解处理支持;然而, javax.lang.model.* API 不仅限于建模编译时的 Java 结构。

如果有一个基于核心反射支持的 javax.lang.model.* 实现,同样的代码可以用于分析类型的编译时和运行时视图。此外,由于 javax.lang.model.* 基于接口,可以使用运行时模型的特化来更容易地进行替代注解语义的实验。

例如,有些人主张语言的注解功能应该更改为支持 stereotyping,其中一个注解的应用在逻辑上将扩展为一组其他注解。要通过核心反射在运行时支持这样的功能,需要修改至少一个 javac 和核心反射,以便执行扩展。给定一个合适的 javax.lang.model.* 实现,可以使用 getAnnotation 方法的微小特化来实现 stereotyping,或者其他各种替代的注解语义,而无需修改平台的核心方面。

描述

预期的实现方法是提供一组工厂方法,它们使用适配器将核心反射对象包装到实现相应的 javax.lang.model.* 结构的对象中。例如,当给定一个 java.lang.reflect.Method 对象时,一个方法会返回一个具有 METHOD 类型和匹配名称的 javax.lang.model.element.ExecutableElement 对象,对于其他语言结构也是如此。这种方法显然是可行的,一个概念验证实现进行得很顺利,但是关于设计和实现还有几个待解决的问题:

  • API 应该是特定于 JDK 还是 Java SE 的?
  • 应该暴露多少实现内容以供特化使用?
  • 是否应该更新标准的 javax.lang.model.* 以更好地支持这个用例?严格来说,javax.lang.model.* 的特定要求仅适用于在注解处理过程中使用 API 时。
  • 是否应该提供一个专门用于运行时的 javax.lang.model.* API 的特化,以访问核心反射特定的功能,比如调用方法?

测试

javax.lang.model.* 的实现进行测试的主要挑战不是单纯地测试所有方法,而是在不同种类的语言结构上测试所有方法。语言模型 API 的底层结构是被建模的语言。例如,为了彻底测试 getModifiers 方法,应该针对每种可以具有修饰符的元素(类型、变量、参数等)探测每个合法修饰符集的组合,即使对于这个简单的行为来说,也是几十种组合。

风险和假设

核心反射与纯语言模型之间的阻抗不匹配可能会复杂化实现。为了合理地处理合成结构,一个专门为核心反射特化的 API 的动机是必要的,合成结构在纯语言模型之外。

依赖

对核心反射 API 进行各种调整,其中一些已经在 JDK 8 构建中进行了修改,将简化 javax.lang.model.* 的实现。例如,MethodConstructor 的新的 Executable 超类有助于代码共享。

假设已经实现了对方法/构造函数参数名称的运行时访问,这个项目自然是那些功能的客户端。

影响

  • 兼容性:基于核心反射和基于 javacjavax.lang.model.* 的行为会有一些差异。
  • 安全性:将使用核心反射的基本安全机制。
  • TCK:如果此 API 作为 Java SE 的一部分发布,可能有一些 JCK 测试用于测试 API。