2010-08-29 44 views
2

我有一個簡單的RMI'compute'服務器應用程序(類似於this),它通過RMI從客戶端接受某些接口類型的對象,執行接收對象的compute()方法,並通過RMI返回結果遠程客戶端。這些工作是「一次性」的,不同工作之間或不同工作對象之間沒有互動。卸載通過RMI傳遞的類

我希望能夠修改類並將實例提交給計算服務器以供執行,而無需不斷重新啓動服務器JVM。然而,當一個已被修改的類再次作爲參數提交給遠程調用時,它的方法行爲不會改變(這也發生在匿名類中)。我一直在閱讀關於序列化的知識,並且我意識到這是因爲ClassLoader無法修改現有類。

從我對SO和其他地方的閱讀中我發現,不知怎麼的,加載流類的ClassLoader必須GC'd並替換爲加載我的類的新版本。我有一個想法如何做到這一點,但底層RMI運行時情況似乎很複雜,並且它有自己的RMIClassloader。

我的問題是:加載通過RMI參數收到的每個新版本的類最簡單的方法是什麼?理想情況下,我正在尋找一種方法讓每個遠程調用都能得到一個新的ClassLoader,並在返回時處理它。沒有關於定製ClassLoaders和RMI內部的複雜知識,這是否可行?

歡迎閱讀材料或例子的任何指針!

編輯:這裏是計算服務器的遠程接口:

public interface ComputationEngine extends Remote { 
    public Object execute(Task t) throws RemoteException; 
} 

和「計算工作」界面,Task

public interface Task extends java.io.Serializable { 
    public Object compute(); 
} 
+1

它不是類加載器必須GCed(雖然你最終會耗盡內存,如果它不是)。 IIRC,在部分RMI實現中,有一個從代碼庫到'ClassLoader'的映射。 – 2010-08-29 15:10:24

+0

什麼是compute()的參數?客戶端是否發送他們想要執行的類文件,或者您是否正在嘗試動態更新compute()接口的實現,因爲出現錯誤而無需重新啓動服務器? – 2010-08-29 16:42:39

+0

@ Tom:我的印象是,卸載類的唯一方法是GC調用'ClassLoader'。從我的實驗看來,所有遠程調用都使用相同的「ClassLoader」。不過謝謝,我會使用這些術語進行更多搜索。 – willjcroz 2010-08-29 20:19:16

回答

0

這是不是真的回答你的問題,但它可能可以將你的類的一部分改爲數據而不是實際的類。使用Map而不是字段等等。您的類會少得多,而且您的代碼也可能會更簡單。

+1

這是一個通用計算服務器(就像在RMI的Java教程中一樣)。當需要改變字節碼指令的代碼時,搞砸數據不會起作用。 – 2010-08-29 15:12:05

+0

謝謝你的想法,就像湯姆說,雖然我依靠更新發送到服務器的類的**行爲**(即方法代碼)(我已更新問題以使其更清晰)。 – willjcroz 2010-08-29 20:47:37