1

我有一个相当大的Java代码库(〜15k文件),我无法访问源,但是,我想在运行时修改某些类并将代码注入某些方法也可以调用我的代码。使用ASM或CGLib的Java依赖注入

由于技术问题,我无法反编译/重新编译,并从那里去。类文件由本机代码加载,并从自定义存档格式中提取,并使用自定义类加载器加载。然而,我可以很容易地在他们的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代理将启用此功能,但与代理,开销高,由于对方法的字符串比较可能被调用几十万我发现为了有一个增强对象的实例,您需要自己实例化它们。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()); 

} 

第一次印刷nts一个真正的对象散列,而不是0。

所以现在我想我需要做的是编写自己的(或修改他们)ClassLoader,寻找我感兴趣的类修改,注入我的修改,并从那里使用类似ASM的东西。 (我使用JVMTI和C++做了类似的工作,但编译/调试过程非常耗时)

在我这样做之前,我希望有一些工作类似于CGLib代理如何工作,因为该库负责所需的字节码修改,但这并不要求我实际实例化所述增强类的实例。

回答

0

我不知道CGLIB是否将Java代码注入Java类是理想的 - 但有一些框架,如f.e. javassist提供以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

+0

看起来很有趣。 javassist看起来很容易注入代码。我有一个疑问,你如何获得你的代码执行? – Raindog

+0

所以你需要访问你正在扩展的应用程序的罐子? – Raindog

+0

我的意思是说你正在扩展的应用名为foo。要运行它,你需要执行java -jar foo.jar。在正常情况下,你如何为foo.jar添加一个插件 – Raindog