是否可以在Java中进行猴子修补,如果没有替代方案?

Gri*_*rim 10 java monkeypatching

这是8年前在这里被问到的,从那时起已经过了8年.我想再次问这个问题,看看是否有人开发了一个猴子修补的框架,工具或库.

基本上我需要它是一个java应用程序,我应用自己的补丁.由于这个项目由另一个团队维护,我希望能够保留/应用我制作的任何补丁,以及他们制作的补丁.

Ric*_*ich 14

有许多技术可能适用于此处,但您的问题过于模糊,无法将其缩小为单一答案.

"猴子修补"在字面意义上表示它在Ruby中使用(即"在运行时替换类的方法",参见例如[1])可以使用"Java代理"和"转换"API,但它更难比在Ruby中.

源代码修补

我需要它为我应用自己的补丁的Java应用程序

如果有一个你有源代码的应用程序,比如说git,那么你可以分叉他们的项目,应用你自己的补丁并构建一个修改后的版本.

我希望能够继续将我制作的任何补丁应用到他们制作的补丁中.

如果您在分支上创建补丁,那么将git来自"上游"项目的任何未来更改引入您的分支将很容易,并构建新的修改版本.

通过类路径优先级在类加载时替换类

一种更接近Monkey Patching的简单技术是从目标应用程序编译单个类,并进行修改,并将其放在类路径上,而不是原始JAR.(这个答案在旧的Monkey Patching q中有所涉及:https://stackoverflow.com/a/381240/8261)

JVM按名称加载所有类,并将使用它在任何类的类路径中找到的第一个类文件,因此您可以从要修改的项目中逐个替换类.如果您拥有目标项目的源,则将其逐个文件复制到应用程序中,然后将修补程序应用于Java源代码.

(您需要使用此方法手动应用任何未来的上游更改.)

在类加载时转换类或通过JVM代理随时"重新转换"方法体

JVM有一个名为" Java Agents " 的API ,它允许您注册代码以在加载时修改类.

还有一个"重新转换 "API,允许您更改已加载的类的定义.JRebel使用来更新正在运行的应用程序中的代码.Ruby的修补更加局限于你不能添加或删除方法(你可以改变方法体).

例如,https://github.com/fommil/class-monkey使用此机制来"猴子补丁"JVM错误.


G_H*_*G_H 5

“纯粹的”猴子修补需要动态语言,而 Java 则不然。所以从技术上来说这是不可能的。进行运行时更改的最佳选择是进行字节码操作。用于此类工作的通用库是ASM