作者 | A N M Bazlur Rahman
译者 | 张卫滨
策划 | 丁晓昀
JEP 457,类文件API(Class-File API,预览),最近已经集成到了 JDK 22 中。该 JEP 建议提供一个 API 来解析、生成和转换 Java 类文件。它最初将作为 JDK 中 Java 字节码操作和分析框架ASM的内部替代品,并计划将其作为公共 API 开放。甲骨文的 Java 语言架构师Brian Goetz将 ASM 描述为“带有大量遗留包袱的旧代码库”,并提供了关于该草案将如何发展并最终取代 ASM 的背景信息。
类文件 API 的核心是几项关键原则。首先,它将类文件实体(比如字段、方法、属性和字节码指令)均视为不可变对象。这种不可变的表述确保在类文件转换时可以可靠地进行共享。该 API 采用树形结构来反映类文件的层次结构,从而支持用户驱动的导航以进行高效地解析。它还强调了解析过程的延迟性,即只会处理满足用户需求所需的类文件。
类文件 API 位于java.lang.classfile包及其子包中,包含三个主要的抽象,即元素、构建器和转换。元素是类文件组件的不可变描述。构建器对应于每种复合元素,可以使用特定的构建方法来方便地构造类文件。转换表示在构建过程中修改元素的函数。
该 API 还引入了使用模式解析类文件的新方法,与 ASM 基于访问者(visitor)的方式有所不同。这支持更直接和更简洁的表达式,利用了 Java 的模式匹配功能。例如,开发人员可以遍历 CodeModel 中的指令,并匹配感兴趣的元素,以完成像依赖图构造这样的任务。
考虑如下的样例:
CodeModel code = ...; Set<ClassDesc> deps = new HashSet<>(); for (CodeElement e : code) { switch (e) { case FieldInstruction f -> deps.add(f.owner()); case InvokeInstruction i -> deps.add(i.owner()); // ... and so on for instanceof, cast, etc ... } }
复制代码
这个代码片段展示了使用模式匹配来解析 Code 属性以收集类依赖关系图的依赖,迭代指令并匹配特定的类型。
使用构建器生成类文件是另一项关键特性。该 API 颠覆了使用构造函数或工厂创建构建器的传统习惯,相反,客户端提供一个接受构建器的 lambda。这种方法提供了更具体和透明的代码生成,并且可以重放操作序列。它还为管理块范围、局部变量索引计算和标签管理提供了更高级的便利性。
下面的代码展示了如何使用构建器生成方法,演示了该 API 具体且透明的代码生成方式。
ClassBuilder classBuilder = ...; classBuilder.withMethod("fooBar", MethodTypeDesc.of(CD_void, CD_boolean, CD_int), flags, methodBuilder -> methodBuilder.withCode(codeBuilder -> { Label label1 = codeBuilder.newLabel(); Label label2 = codeBuilder.newLabel(); codeBuilder.iload(1) .ifeq(label1) .aload(0) .iload(2) .invokevirtual(ClassDesc.of("Foo"), "foo", MethodTypeDesc.of(CD_void, CD_int)) .goto_(label2) .labelBinding(label1) .aload(0) .iload(2) .invokevirtual(ClassDesc.of("Foo"), "bar", MethodTypeDesc.of(CD_void, CD_int)) .labelBinding(label2) .return_(); });
复制代码
类文件的转换功能同样值得注意。解析和生成方法保持了一致,这样转换可以无缝进行。例如,开发人员可以处理一个类,以便于删除特定的方法,或者通过应用各种转换来改变方法体。
下面的代码片段展示了 API 的转换类文件的功能,演示了在转换过程中如何有选择地修改或替换类元素。
ClassFile cf = ClassFile.of(); ClassModel classModel = cf.parse(bytes); byte[] newBytes = cf.transform(classModel, (classBuilder, ce) -> { if (ce instanceof MethodModel mm) { classBuilder.transformMethod(mm, (methodBuilder, me)-> { if (me instanceof CodeModel cm) { methodBuilder.transformCode(cm, (codeBuilder, e) -> { switch (e) { case InvokeInstruction i when i.owner().asInternalName().equals("Foo") -> codeBuilder.invokeInstruction(i.opcode(), ClassDesc.of("Bar"), i.name().stringValue(), i.typeSymbol(), i.isInterface()); default -> codeBuilder.with(e); } }); } else methodBuilder.with(me); }); } else classBuilder.with(ce); });
复制代码
JEP 457 具有变革性的一个方面是如何解决 Java 生态系统中类文件格式的快速发展所带来的挑战。通过提供与 JDK 一起演进的标准 API,它能够确保使用该 API 的框架和工具会自动支持来自最新 JDK 的类文件。这种能力对于新语言和 VM 特性非常重要,它们在类文件中可能会有相应地表述。
总之,JEP 457 的类文件 API 是一种具有前瞻性的解决方案,符合 Java 开发的现代化需求。它的设计原则、抽象和转换功能使其成为 Java 开发人员的强大工具,增强了 Java 生态系统中类文件管理的效率和可靠性。
原文链接:Java架构师:ASM已经过时,建议使用类文件API简化开发_编程语言_A N M Bazlur Rahman_InfoQ精选文章
到此这篇Java 架构师:ASM 已经过时,建议使用类文件 API 简化开发_asm文件类型的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/javal-jgs/6431.html