1

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

4

1 回答 1

0

我不知道是否CGLIB适合将 Java 代码注入 Java 类 - 但有几个框架,如 fe javassist,它提供了一种以 Java 为中心的方式将代码注入非密封的 Java 类:http://www.csg .ci.iu-tokyo.ac.jp/~chiba/javassist/

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

于 2013-10-22T19:21:54.603 回答