2010-08-29 127 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