JEP 457:用于解析、生成、转换 Java 类文件的类文件 API


提供用于解析、生成和转换 Java 类文件的标准 API。这是一个预览 API

目标

  • 提供准确、完整、高性能、标准的 API,用于读取、写入和转换 Java 类文件,跟踪类文件规范。
  • 能够替换 JDK 中现有的ASM使用,最终能够删除 JDK 的 ASM 库的内部副本。我们也许可以类似地删除 JDK 的两个自定义内部类文件库。

非目标

  • 我们的目标不是淘汰生态系统中的其他类文件处理库,也不是成为世界上最快的类文件 API。
  • 扩展运行时反射以访问加载类的方法体的字节码并不是目标。
  • 提供代码分析功能不是目标;而是提供代码分析功能。可以通过第三方库在此 API 之上分层。

类文件生成、解析和检测在 Java 生态系统中无处不在。许多工具和库处理类文件,并且框架通常执行动态字节码检测、转换和生成。
Java 生态系统有许多不同的类文件解析和生成库,每个库都有不同的设计目标、​​优点和缺点。在过去的十年中,JDK 在其实现中广泛使用了ASM库,用于 lambda 代理生成等任务。

然而:
1、JVM 的发展——JVM 和类文件格式现在的发展速度比该平台早年要快得多。

2、JDK 整合 - JDK 本身就是一个重要的类文件使用者商。由于历史原因,它包含四个不同的内部类文件库:

  • jdk.compiler 模块中的自定义库,由 javac 编译器和 javadoc 工具使用;
  • jdk.jdeps 模块中的另一个自定义库,由 javap、jdeps、jdeprscan 和 jlink 工具使用;
  • java.xml 模块中的 BCEL 分支,用于 Xalan 分支;以及
  • java.base 模块中的 ASM 分支,用于实现 lambdas、方法句柄、模块、动态代理、JFR 以及 jar、jimage、jlink 和 jshell 工具。

就 ASM 而言,使用它来实现平台的基本元素会延迟新类文件功能的使用。

JDK N 的 ASM 版本在 JDK N 最终定型之前无法定型,因此 JDK 工具(如 jlink)无法处理 JDK N 中的新类文件功能,因此 javac 在 JDK N+1 之前无法生成 JDK N 中的新类文件功能。

JDK 开发人员需要一个与 JVM 保持同步的类文件库。

3、框架和正在运行的 JDK 之间的版本偏差- 使用处理类文件的框架的应用程序通常捆绑一个类文件库。但是新的类文件功能可能会出现在任何 JDK 版本中,而且 JDK 9 之后 JDK 的发布速度大大加快,因此应用程序更频繁地遇到比它们捆绑的库更新的类文件。这会导致运行时错误,或者更糟糕的是,框架会尝试解析未来的类文件,并相信没有任何严重的变化。应用程序和框架开发人员需要一个类文件库,他们可以依靠该库来与正在运行的 JDK 保持同步。

这是预览版 API,默认禁用
要在 JDK 22 中尝试以下示例,您必须启用预览功能,如下所示:

  • 使用 编译程序并使用;javac --release 22 --enable-preview Main.java运行它 java --enable-preview Main或者,
  • 使用源代码启动器时,运行程序java --source 22 --enable-preview Main.java

网友评论:
1、这非常令人兴奋...在我的职业生涯中,我已经使用过所有库:CGLib、ASM、BCEL、ByteBuddy、Javassist 等...每个库都有其优点和缺点。我设计了一切,从分析代理,到将小数打包到 EBCDIC 并在大型 IBM 机器上调用 COBOL 程序的系统,再到轻量级 JIT 编译器,所有这些都使用这些库。

 2002年,ASM使用的访问者模式 看起来很聪明,但是访问者模式很难解释/证明,并且仍然很难向刚刚进入该行业的新手程序员解释。

这个预览API将是 ASM 的正式替代品,这意味着它将是相当低的水平,而且将会使得Stream流的使用非常简单。
当然类似于 ByteBuddy 或 Javassist 的更高级别 API 还是有存在需求的。

2、将对从一个 JDK 更新到下一个 JDK 的生态系统产生巨大影响。
我们在升级 JDK 版本时看到的最令人头痛的问题之一是字节码生成/操作库在新版本的 JDK 上出现问题。通常这是一个简单的更新,但有时并非如此(例如,当有人对 asm 进行着色时)。

这可能是我从 Java 11 到 17、从 17 到 21 所经历的 80% 的头痛。

将字节码生成作为 JDK 的一部分意味着所有库(包括 asm)都可以迁移到该库,并从像 JDK 一样更新的永久支持的 API 中受益。

3、Lombok 令人头疼的原因是它们通过进入 Java 编译器内部来实现它们的魔力。这并不能解决这个问题。
如果 Lombok 只是进行简单的字节码操作,那么它就不会遇到同样的麻烦。
如果 lombok 想要停止痛苦,那么他们就需要停止触及内部 API。他们可能需要删除一些功能。
换句话说,lombok 在未来几年都会成为令人头疼的问题。