使用ASM或CGLib的Java依赖项注入
我有一个相当大的Java代码库(~15k文件),我没有访问源代码的权限,但是,我想在运行时修改某些类,并将代码注入某些方法中,以便也调用我的代码 由于技术问题,我无法反编译/重新编译并从那里开始。类文件由本机代码加载,并从自定义存档格式提取,然后使用自定义类加载器加载。但是,我可以相当轻松地在JVM实例的上下文中执行Java代码 我的目标是做如下事情: 例如,假设代码中有一个类:使用ASM或CGLib的Java依赖项注入,java,dependency-injection,java-bytecode-asm,cglib,bytecode-manipulation,Java,Dependency Injection,Java Bytecode Asm,Cglib,Bytecode Manipulation,我有一个相当大的Java代码库(~15k文件),我没有访问源代码的权限,但是,我想在运行时修改某些类,并将代码注入某些方法中,以便也调用我的代码 由于技术问题,我无法反编译/重新编译并从那里开始。类文件由本机代码加载,并从自定义存档格式提取,然后使用自定义类加载器加载。但是,我可以相当轻松地在JVM实例的上下文中执行Java代码 我的目标是做如下事情: 例如,假设代码中有一个类: class Theirs { public Theirs() { //.... }
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代理可以实现这一点,但使用代理时,由于对每秒可能被调用数十万次的方法进行字符串比较,因此开销很高。无论如何,我发现为了拥有增强对象的实例,您需要自己实例化它们。。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
所以现在我想我需要做的是编写我自己的(或修改他们的)类加载器,查找我感兴趣修改的类,注入我的修改,然后使用类似ASM的东西从那里开始。(我使用JVMTI和C++做了类似的事情,但是编译/调试过程非常耗时)
然而,在我这么做之前,我希望有一种类似于CGLib代理的工作方式,即库处理所需的字节码修改,但这并不要求我实际实例化所述增强类的实例。我不知道
CGLIB
是否是将Java代码注入Java类的理想选择-但有两种类似于f.e.javassist的框架可用,它们提供了一种以Java为中心的方式将代码注入非密封Java类:
例如,我曾经使用javassist为大学课程创建了一个插件机制。希望代码示例有帮助:看起来很有趣。javassist看起来非常容易注入代码。但是我有一个问题,你如何获得代码的执行?所以你需要访问你正在扩展的应用程序的jar?我的意思是,假设你正在扩展的应用程序名为foo。要运行它,需要执行java-jarfoo.jar。在正常情况下,如何向foo.jar添加插件