我有一个相当大的 Java 代码库(~15k 文件),我无法访问其源代码,但是,我想在运行时修改某些类并将代码注入(inject)某些方法中以调用我的代码。
由于技术问题,我无法反编译/重新编译并从那里开始。类文件由 native 代码加载,并从自定义存档格式中提取并使用自定义类加载器加载。不过,我可以相当轻松地在 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;
}
}
我想修改 Theirs 的每个实例,使其行为如下:
class Theirs {
public Theirs() {
Mine.myMethod(this);
}
}
这样我就可以做类似的事情:
System.out.println(Mine.theirs_.getName());
我认为 CGLib 代理可以实现这一点,但是对于代理,由于每秒可能调用数十万次的方法的字符串比较,开销很高,无论如何,我发现为了拥有一个实例,增强对象,您需要自己实例化它们。 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,它会查找我有兴趣修改的类,注入(inject)我的修改,然后使用 ASM 之类的东西。 (我已经使用 JVMTI 和 C++ 做了类似的事情,但是编译/调试过程非常耗时)
然而,在我这样做之前,我希望有一些类似于 CGLib 代理工作方式的东西,因为该库负责所需的字节码修改,但这并不需要我实际实例化一个实例说增强类。
最佳答案
我不知道 CGLIB
是否适合将 Java 代码注入(inject) Java 类 - 但有一些框架,例如 f.e. javassist 可用,它提供了一种以 Java 为中心的方式将代码注入(inject)到非密封 Java 类中:http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
例如,我必须为大学类(class)创建一个插件机制,因此我使用了 javassist。希望代码示例有帮助:https://github.com/RovoMe/PluginApplication/blob/master/PluginFramework/PluginCore/src/main/java/at/rovo/core/classloader/InjectionLoaderStrategyDecorator.java
关于使用 ASM 或 CGLib 的 Java 依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19526157/