【问题标题】:Java Bytecode Manipulation Without External Library没有外部库的 Java 字节码操作
【发布时间】:2018-10-07 12:31:40
【问题描述】:

ASM、BCEL、Javaassist 和 AspectJ 等库都能够进行运行时字节码操作,但它们是如何实现的呢?

我之前使用 ASM 完成了一些基本的字节码操作,但我不明白它是如何工作的。 Java Agent 是否在程序的其余部分之前在 JVM 中执行,允许 ASM 在 JVM 执行之前加载编译的类并对其进行编辑?

如果是这样,是否可以在不使用 ASM 等外部库的情况下执行 java 字节码操作,并使用 BufferedReader 加载已编译的类文件并编写自定义解析器等?

【问题讨论】:

  • “外部库”这个词可能有点含糊。无论“外部库”在做什么,理论上您总是可以复制和粘贴他们的代码,然后它们就不再是“外部”了。似乎问题在于如何这些库实际上实现了它们正在做的事情。 (我现在可以再次参考他们的源代码,但是......也许有人可以写一个正确的答案......)
  • 我想第三方库会是一个更好的表达方式,尽管我会研究上述一些库的源代码,但是仍然感谢任何 cmets

标签: java bytecode-manipulation


【解决方案1】:

这些库基于标准 Java API,当然,您也可以在没有这些库的情况下自行使用。

首先,Java 类文件只是格式明确的字节序列,如JVMS §4, The class File Format 中所指定。上述库的主要任务是提供用于处理这种格式的字节序列的工具。第二个是关于获取现有或导出修改或新创建的类的定义。

处理第二个任务有两种不同的方式。一种是从文件系统或 jar 文件等持久存储中读取已编译的类,并在特定代码未运行时将它们写回这些存储,就像构建和部署工具一样。这应该是微不足道的,因为它归结为读取和写入字节。

另一个是在运行时操作类,这可以由 Java 代理通过Instrumentation API 完成。它提供了在第一次使用之前在加载/定义时拦截类的机制,还提供了类的重新定义。后者不能随意更改,目前它必须保留所有的字段和方法声明,所以主要用于更改方法的可执行代码。

如果您想要在没有额外的 3rd 方库的情况下进行类文件处理的示例,Stackoverflow 上有一些答案

当然,这些示例只是单一用途的代码或草图。如果您将它们扩展为更通用或更有用的东西,您很快就会基本上重新实现这些库。

【讨论】:

  • 感谢您的深入回复,我的理解非常相似,但我感谢您的澄清和示例
【解决方案2】:

类文件只是一个字节序列,其格式在The Java Virtual Machine Specification 中指定。 BufferedReader 是文本文件,所以你想要BufferedInputStream,但格式相当复杂。

您可以加载被操纵的类文件,就好像它们是由javac 生成的一样。您还可以使用java.net.URLClassLoader.newInstance 或类似名称动态加载它们。 Java 代理允许在加载类文件时通过 Java 或本机接口修改类文件(如果您想修改在加载类的类之前加载的类,则后者是必需的)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多