Java 卸载通过RMI传递的类

Java 卸载通过RMI传递的类,java,rmi,classloader,Java,Rmi,Classloader,我有一个简单的RMI“compute”服务器应用程序(类似于),它通过RMI从客户端接收某些接口类型的对象,执行所接收对象的compute()方法,并通过RMI将结果返回给远程客户端。作业是“一次性”的,不同作业之间或不同作业对象之间没有交互 我希望能够修改类并将实例提交给计算服务器执行,而无需不断重新启动服务器JVM。但是,当已修改的类作为参数再次提交给远程调用时,它的方法行为不会改变(匿名类也会发生这种情况)。我一直在阅读有关序列化的内容,我意识到这与类加载器无法修改现有类有关 从我在SO和

我有一个简单的RMI“compute”服务器应用程序(类似于),它通过RMI从客户端接收某些接口类型的对象,执行所接收对象的
compute()
方法,并通过RMI将结果返回给远程客户端。作业是“一次性”的,不同作业之间或不同作业对象之间没有交互

我希望能够修改类并将实例提交给计算服务器执行,而无需不断重新启动服务器JVM。但是,当已修改的类作为参数再次提交给远程调用时,它的方法行为不会改变(匿名类也会发生这种情况)。我一直在阅读有关序列化的内容,我意识到这与类加载器无法修改现有类有关

从我在SO和其他地方的阅读中,我意识到加载流类的类加载器必须被GC’d并替换,以便加载我的类的新版本。我知道如何做到这一点,但由于底层RMI运行时和它有自己的RMI类加载器,情况似乎很复杂

我的问题是:加载通过RMI参数接收的类的每个新版本的最简单方法是什么。理想情况下,我正在寻找一种方法,让每个远程调用获得一个新的类加载器,并在返回时处理它。如果没有定制类加载器和RMI内部的复杂知识,这是可行的吗

欢迎任何阅读材料或示例的指点

编辑:这是计算服务器的远程接口:

public interface ComputationEngine extends Remote {
    public Object execute(Task t) throws RemoteException;
}
以及“计算作业”界面,
任务

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

这并不能真正回答您的问题,但可以将部分类更改为数据,而不是实际的类。使用
映射
而不是字段等。这样可以减少浮动的类,代码也可能更简单

当您想要更改类时,唯一的方法是使用新的类加载器。 如何使用URLClassLoader并使代码从URL中可用

我在我的一个项目中使用它来更新jar文件更改时的API。请看这里: 第184行+


检查您的电子邮件:-)

这不是类加载器需要GCed的唯一方法(尽管如果不是,您最终会耗尽内存)。IIRC,在RMI实现的一部分中,有一个从codebase到
ClassLoader
的映射。要计算的参数是什么()?客户机是否正在发送他们想要执行的类文件,或者您只是试图在出现错误时动态更新compute()接口的实现,而不必重新启动服务器?@Tom:我的印象是,卸载类的唯一方法是GC
类加载器
。从我的实验来看,似乎所有远程调用都使用相同的
类加载器。不过,谢谢,我将使用这些术语进行更多搜索。@bMail:客户端正在发送自定义类(实现
任务
)的对象以供执行。我希望能够修改/调整客户端“作业”类的方法代码,重新提交作业,然后能够在不重新启动服务器JVM的情况下观察新行为。谢谢:-)将同时收集
类加载器及其类。如果由不同的类加载实例加载多个具有相同完全限定名的类,则可能会缺少这样的功能。(顺便说一句,通知在'@'和用户名之间不应该有空格。)它是一个通用计算服务器(正如RMI的Java教程中所述)。当字节码指令需要更改时,弄乱数据是没有帮助的。谢谢你的想法,就像Tom说的,尽管我依赖于更新发送到服务器的类的行为(即方法代码)(我更新了问题以使其更清楚)。