我有一个包含 5 个类的 jar 文件。我只想改变该类中的一个逻辑。
BaseClass 是我需要修复的。请检查以下基础结构。
我只需要在 changeMe
方法中删除一行并添加 3 行。
类结构
package com.temp;
public class BaseClass{
public interface IClassA{ String sayRaw(String raw); }
private BaseClass(){}
protected static class ClassToFix extends ClassParent {
@Override public void changeMe () {
........
}
}
}
//---------Source from jar file--------------
package com.temp;
public class ClassA implements IClassA{
public static final BaseClass.IClassA ABC = ....;
String sayRaw(String raw){
}
}
我尝试过的
- 该类没有公共(public)构造函数,因此无法扩展类选项。
- 我尝试了 bytebuddy 的方法拦截器,出现了同样的问题。
- 最后我尝试了javaassist。它也不起作用,因为它没有更新 jar 文件中的方法定义。
我确实在 src 目录中创建了相同的包并复制了类定义并添加了我的修复。此修复适用于动态 Web 项目,但不适用于 Maven Java 项目。提示链接错误
ClassA is implementation of interface (IClassA) from BaseClass which is the modified source.
java.lang.LinkageError: loader constraint violation: when resolving field "ABC" the class loader (instance of org/springframework/boot/devtools/restart/classloader/RestartClassLoader) of the referring class, com/temp/ClassA, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the field's resolved type, com/temp/BaseClass$IClassA, have different Class objects for that type
建议我是否有其他方法可以解决此问题。
最佳答案
您无法在运行时创建不允许在编译时创建的类。 JVM 在加载任何类之前都会对其进行验证,并且将不允许您尝试执行任何操作。
使用 Byte Buddy 或 Javassist,您可以定义一个所谓的 Java 代理,您可以在启动时添加它。这样做,您可以在首次加载时重新定义 ClassToFix
。
Byte Buddy 包含一个 AgentBuilder
抽象,这使得实现起来相当容易。您可以找到tutorials on how to implement an agent online 。 Javassist 不提供定义 Java 代理的机制,但它允许您在创建自己的 ClassFileTransformer
时重新定义类。
关于java - 通过源码包更新现有的类定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38362210/