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