使用 ASM 或 CGLib 的 Java 依赖注入(inject)

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

我有一个相当大的 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/

相关文章:

java - 显示具有 AppCompat 主题的壁纸 (Android)

java - 表单参数未传递但处理了相同表单中的文件?

java - 如何将处理程序注册到使用 XmlAdapter 的 JAXB 注释类,以便向 REST 资源客户端发送错误消息?

java - 如何在 LibGDX 中正确使用 Dagger 2 的场注入(inject)?

java - 具有 ASM 的 JVM INVOKESPECIAL 私有(private)构造函数

spring - 为什么 Cobertura 不能在我的 Spring/Hibernate Webapp 中工作?

java - java中的数组实际上是顺序内存数据结构吗?或物理顺序?

java - Spring Boot DI 使用注入(inject)。类别未被识别

Angular 2 何时使用 DI、提供程序或纯导入?

java - 是否可以使用 ByteBuddy 的建议访问局部变量?