当前位置: 首页 > news >正文

<span class=“js_title_inner“>【Java 25】Class-File API,解析、生成和转换 Java 字节码的标准 API</span>

Class-File API 是 Java 25 中另外一个实用的功能,它提供了解析、生成和转换 Java 字节码的标准 API。

在 Java 相关的开发中,对字节码(byte code)的操作,一直以来被认为是比较高级的技巧。操作字节码需要第三方库的支持,通常使用的库包括 ASM,ByteBuddy 和 Javassist。其中 ASM 是最老牌的库。JDK 内部都集成了 ASM 的代码。

使用第三方库来操作字节码,存在一些问题。第三方库主要依靠社区维护,功能更新和 bug 修复不够及时。最大的问题在于无法及时提供对最新版本 Java 的支持。在一个 Java 版本发布了之后,需要等待第三方库完成修改,才能应用在新的 Java 版本上。

Java 确实需要一个标准的 API 来对字节码进行操作,这就是 Class-File API。

Class-File API 提供的功能包括字节码的解析、生成和转换。在 API 中,有 3 个不同的部分,分别是 model,builder 和 transform。

model 表示的是模型。根据 Java 字节码的规范,API 中定义了字节码中不同部分的模型。这些模型是一系列的接口。比如,表示类的 ClassModel,表示方法的 MethodModel,和表示字段的 FieldModel 等。解析字节码是把字节码的 byte 数组,转换为 ClassModel。

builder 表示的是构建器,用来构建不同类型的 model。比如构建类的 ClassBuilder, 构建方法的 MethodBuilder,和构建字段的 FieldBuilder 等。这些构建器负责产生所对应的 model。ClassBuilder 构建出来的 ClassModel,可以生成字节码的 byte 数组。

transform 表示的是转换,对一个 model 进行修改。在转换时,进行转换的代码会接收到一个 builder,以及当前的 model。代码可以选择保留,删除或是更新当前的 model,从而完成转换。

下面看一下具体的代码示例。

首先是解析字节码。使用 ClassFile 的 of 方法创建出 ClassFile,再使用 parse 方法解析一个类文件,得到表示该类文件的 ClassModel,最后使用 ClassModel 即可。

在下面的代码中,被解析的是当前的 Java 类的字节码,输出全部方法的名称。

public class ParseClass { void parse() throws IOException { var classModel = ClassFile.of().parse( Path.of("target", "classes", "me", "vividcode", "java21to25", "classfile", "ParseClass.class")); var methods = classModel.methods().stream().map(MethodModel::methodName) .collect( Collectors.joining(", ")); System.out.println(methods); } static void main() throws IOException { new ParseClass().parse(); }}

接着是生成字节码。ClassFile 的 buildTo 方法把生成的字节码输出到文件中。使用 ClassBuilder 构建类,在构建过程中,使用 MethodBuilder 来构建方法。

在下面的代码中,生成了 HelloWorld 类。生成的 HelloWorld 类中,有 greet 和 main 两个方法。在 greet 方法中,使用 IO.println 方法输出 “Hello world”。在 main 方法中,调用 greet 方法。生成的字节码写入到 HelloWorld.class 文件中。

publicclassGenerateClass { voidgenerate() throws IOException { var classDesc = ClassDesc.of("HelloWorld"); ClassFile.of() .buildTo(Path.of("target", "classes", "HelloWorld.class"), classDesc, classBuilder -> { classBuilder.withMethod("greet", MethodTypeDesc.of(CD_void), ACC_STATIC, methodBuilder -> { methodBuilder.withCode(codeBuilder -> { codeBuilder.loadConstant("Hello world"); codeBuilder.invoke(Opcode.INVOKESTATIC, ClassDesc.of("java.lang.IO"), "println", MethodTypeDesc.of(CD_void, CD_Object), false); codeBuilder.return_(); }); }); classBuilder.withMethod("main", MethodTypeDesc.of(CD_void), ACC_PUBLIC | ACC_STATIC, methodBuilder -> { methodBuilder.withCode(codeBuilder -> { codeBuilder.invoke(Opcode.INVOKESTATIC, classDesc, "greet", MethodTypeDesc.of(CD_void), false); codeBuilder.return_(); }); }); }); } staticvoidmain() throws IOException { new GenerateClass().generate(); }}

最后是转换字节码,ClassFile 的 transformClass 方法,使用一个 ClassTransform 对 ClassModel 进行转换。

在下面的代码中,对于方法中的调用指令,检查所调用方法的所有者,是否为 OldService。如果是的话,转换为 NewService。这样就把所有对于 OldService 中方法的调用,自动转换为对 NewService 中对应方法的调用。

public class TransformClass { void transform() throws IOException { CodeTransform codeTransform = (codeBuilder, e) -> { switch (e) { case InvokeInstruction i when i.owner().asInternalName() .contains("OldService") -> codeBuilder.invoke(i.opcode(), ClassDesc.of( "me.vividcode.java21to25.classfile.totransform.NewService"), i.name().stringValue(), i.typeSymbol(), i.isInterface()); default -> codeBuilder.accept(e); } }; var methodTransform = MethodTransform.transformingCode(codeTransform); var classTransform = ClassTransform.transformingMethods( methodTransform); var packagePath = Path.of("target", "classes", "me", "vividcode", "java21to25", "classfile", "totransform"); var classModel = ClassFile.of().parse( packagePath.resolve("ServiceCaller.class")); var bytes = ClassFile.of() .transformClass(classModel, classTransform); Files.write(packagePath.resolve("ServiceCaller.class"), bytes, StandardOpenOption.TRUNCATE_EXISTING); } static void main() throws IOException { new TransformClass().transform(); }}

有了 Class-File API,我们不再需要使用第三方库来操作 Java 的字节码。这样减少了第三方依赖,也提高了代码的可维护性。

http://www.jsqmd.com/news/336032/

相关文章:

  • <span class=“js_title_inner“>[今日战况]创新高了!黄金有色吃大肉!ETF三因子轮动实盘跟踪!股票量化分析工具QTYX-V3.3.6</span>
  • <span class=“js_title_inner“>彻底爆了!阿里最新大模型,再次拿下第一!</span>
  • <span class=“js_title_inner“>[NEW]六边形量化框架升级,全自动三因子轮动策略!股票量化分析工具QTYX-V3.3.5</span>
  • <span class=“js_title_inner“>对话段永平:做自己能够喜欢的事情很重要</span>
  • <span class=“js_title_inner“>支配树算法原理及鸿蒙工具实践</span>
  • 2026年口碑好的柬埔寨至东莞国际物流专线/东莞至柬埔寨国际物流专线往返综合情况汇总 - 行业平台推荐
  • 2026年知名的柬埔寨老拗至东莞国际物流专线/金瑞通国际物流专线服务情况参考 - 行业平台推荐
  • <span class=“js_title_inner“>AI也“做梦”和“减肥”?一文读懂大模型的幻觉与蒸馏</span>
  • Cybersecurity AI (CAI) AI 时代的网络安全自动化框架
  • 【工具】Python解释器和PyCharm的安装与使用
  • 2026年靠谱的威海法律咨询律师事务所/威海金融律师事务所本地选择建议榜 - 行业平台推荐
  • 2026年比较好的威海法律咨询律师事务所/威海离婚律师事务所本地口碑推荐榜 - 行业平台推荐
  • 2026年热门的储能/电化学储能厂家推荐必看 - 行业平台推荐
  • 2026年,如何甄选一家诚信可靠的工程石材供应商? - 2026年企业推荐榜
  • 2026年评价高的混合储能/西安石油矿山储能厂家信誉综合参考 - 行业平台推荐
  • 树莓派5+ubuntu24.04+openclaw使用记录
  • 2026年知名的西安长循环寿命电池/液流电池用户口碑认可参考(高评价) - 行业平台推荐
  • 深度解析:如何选择可靠的热蒸发镀膜机技术团队 - 2026年企业推荐榜
  • 2026河北镀膜机优质企业综合评测与选型指南 - 2026年企业推荐榜
  • 2026年初优质金属锥体供应商综合评估与选型指南 - 2026年企业推荐榜
  • 河北原子层沉积镀膜机服务团队综合评估与精选推荐 - 2026年企业推荐榜
  • 2026年江苏封头厂家综合实力对比与选购指南 - 2026年企业推荐榜
  • 2026年企业大模型优化服务商选型指南与市场全景分析 - 2026年企业推荐榜
  • 2026年初武汉广告装饰公司选购指南与优质服务商推荐 - 2026年企业推荐榜
  • 2026年江苏封头制造厂商综合实力评估与选购指南 - 2026年企业推荐榜
  • <span class=“js_title_inner“>黄渤把亲父送养老院,主持人问他:你年入过亿,还送养老院?黄渤含泪说出7个字</span>
  • 2026年湖北LOWE玻璃实力公司深度盘点与选购指南 - 2026年企业推荐榜
  • 2026年值得信赖的24小时自助棋牌室加盟品牌推荐 - 2026年企业推荐榜
  • 2026年湖南棋牌室加盟市场深度评测与品牌推荐 - 2026年企业推荐榜
  • 2026年评价高的贴皮木门/实木门厂家采购参考指南(必看) - 行业平台推荐