使用ASM或CGLib进行Java依赖注入

时间:2013-10-22 19:01:51

标签: java dependency-injection java-bytecode-asm cglib bytecode-manipulation

我有一个相当大的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代理工作的东西,因为库负责所需的字节码修改,但这并不需要我实际实例化一个实例说增强课程。

1 个答案:

答案 0 :(得分:0)

我不知道CGLIB是否适合将Java代码注入Java类 - 但是有一些框架就像f.e. javassist available,提供以Java为中心的方式将代码注入非密封的Java类:http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/

例如,我曾经使用javassist为大学课程创建了一个插件机制。希望代码示例很有用:https://github.com/RovoMe/PluginApplication/blob/master/PluginFramework/PluginCore/src/main/java/at/rovo/core/classloader/InjectionLoaderStrategyDecorator.java