2011-01-28 51 views
35

JRebel使用Javassist還是某種字節碼操作?我只是出於純粹的興趣問我,實際上我並不需要知道:)JRebel如何工作?

回答

43

JRebel使用類重寫(包括ASM和Javassist)和JVM集成到個別類的版本。此外,它還與應用服務器集成,將類/資源和Web服務器查找重定向回工作區。它還與大多數應用程序服務器和框架集成,以將更改傳播到配置(元數據或文件)。這就是它的缺點。這需要10名世界級工程師來開發和支持,並且是我們的商業祕密:)

+2

@Jevgeni卡巴諾夫:是否JRebel的處理final類的重裝? – Dexter 2013-03-28 14:24:52

4

這是我讀過的關於Simon,ZT技術傳播者JRebel works最接近的推理。

粘貼的內容在這裏:


JRebel的儀器應用和JVM類來創建間接層。在加載應用程序類的情況下,所有方法體將使用運行時重定向服務進行重定向,如圖2所示。該服務使用爲每個重新加載的版本創建的匿名內部類來管理和加載類和方法版本。我們來看一個例子。我們將創建一個新的C級有兩種方法:

public class C extends X { 
int y = 5; 
int method1(int x) { 
    return x + y; 
} 
void method2(String s) { 
    System.out.println(s); 
} 
} 

當C類加載首次,JRebel的儀器類。這個類的簽名將是相同的,但方法體現在被重定向。加載的類現在看起來是這樣的:

public class C extends X { 
int y = 5; 
int method1(int x) { 
    Object[] o = new Object[1]; 
    o[0] = x; 
    return Runtime.redirect(this, o, "C", "method1", "(I)I"); 
} 
void method2(String s) { 
    Object[] o = new Object[1]; 
    o[0] = s; 
    return Runtime.redirect(this, o, "C", "method2", "(Ljava/lang/String;)V"); 
} 
} 

要重定向來電,我們傳遞調用對象的參數的方法,該方法被調用,我們班的名字,我們的方法名稱和類型參數和返回。 JRebel的也是在一個特定的版本加載與實現一類,最初版本0讓我們來看看是什麼樣子:

public abstract class C0 { 
public static int method1(C c, int x) { 
    int tmp1 = Runtime.getFieldValue(c, "C", "y", "I"); 
    return x + tmp1; 
} 
public static void method2(C c, String s) { 
    PrintStream tmp1 = 
    Runtime.getFieldValue(
     null, "java/lang/System", "out", "Ljava/io/PrintStream;"); 
    Object[] o = new Object[1]; 
    o[0] = s; 
    Runtime.redirect(tmp1, o, "java/io/PrintStream;", "println","(Ljava/lang/String;)V"); 
} 
} 

現在,讓我們說,用戶通過添加新的方法,Z()和調用改變了他們的C類它來自method1。 C類現在看起來是這樣的:下一次運行時間

public class C { 
int y = 5; 
int z() { 
    return 10; 
} 
int method1(int x) { 
    return x + y + z(); 
} 
... 
} 

使用這個類,JRebel的檢測也已被編譯並在文件系統的新版本,所以它加載新的版本,C1。此版本具有其他方法z和方法1的更新實現。

public class C1 { 
public static int z(C c) { 
    return 10; 
} 
public static int method1(C c, int x) { 
    int tmp1 = Runtime.getFieldValue(c, "C", "y", "I"); 
    int tmp2 = Runtime.redirect(c, null, "C", "z", "(V)I"); 
    return x + tmp1 + tmp2; 
} 
... 
} 

的Runtime.redirect通話將永遠被路由到C級的最新版本,因此調用new C()方法1(10)將返回15碼改變之前和之後25。這個實現忽略了很多細節和優化,但你明白了。

來源:http://zeroturnaround.com/rebellabs/why-hotswap-wasnt-good-enough-in-2001-and-still-isnt-today/