我有一个相当大的 Java 代码库(约 15k 个文件),我无法访问其源代码,但是,我想在运行时修改某些类并将代码注入某些方法以调用我的代码。
由于技术问题,我无法反编译/重新编译并从那里开始。类文件由本机代码加载,并从自定义存档格式中提取并使用自定义类加载器加载。然而,我可以相当容易地在他们的 JVM 实例的上下文中执行 Java 代码。
我的目标是执行以下操作:
例如,假设代码中有一个类:
class Theirs {
public Theirs() {
//....
}
public String getName() {
return "Theirs";
}
}
在我的代码中,我有:
class Mine
{
public static Theirs theirs_ = null;
public static void myMethod(Theirs theirs) {
theirs_ = theirs;
}
}
我想修改他们的每个实例以使其行为如下:
class Theirs {
public Theirs() {
Mine.myMethod(this);
}
}
这样我就可以执行以下操作:
System.out.println(Mine.theirs_.getName());
我认为 CGLib Proxies 可以实现这一点,但是使用 Proxies,由于对可能每秒调用数十万次的方法进行字符串比较,开销很高,无论如何,我发现为了获得增强对象的实例,您需要自己实例化它们.. IE:并非您增强的类的所有实例实际上都得到了增强,例如:
public static void main( String[] args )
{
Object proxy = Enhancer.create(Object.class, new HashCodeAlwaysZeroMethodInterceptor());
System.out.println(new Object().hashCode());
System.out.println(proxy.hashCode());
}
第一个 println 打印一个真实的对象散列,而不是预期的 0。
所以现在我在想我需要做的是编写我自己的(或修改他们的)ClassLoader,它会查找我有兴趣修改的类,注入我的修改,然后使用 ASM 之类的东西从那里开始。(我使用 JVMTI 和 C++ 做过类似的事情,但是编译/调试过程非常耗时)
然而,在我这样做之前,我希望有一些类似于 CGLib 代理的工作方式的东西,因为该库负责所需的字节码修改,但这并不需要我实际实例化所述增强类的实例.