卸载通过 RMI 传递的类
我有一个简单的 RMI“计算”服务器应用程序(类似于 this )通过 RMI 从客户端接受某种接口类型的对象,执行接收到的对象的compute()方法,并通过 RMI 将结果返回到远程客户端。这些作业是“一次性”的,不同作业之间或不同作业的对象之间没有交互。
我希望能够修改类并将实例提交到计算服务器来执行,而无需不断重新启动服务器 JVM。但是,当已修改的类再次作为参数提交给远程调用时,它的方法行为不会改变(匿名类也会发生这种情况)。我一直在阅读有关序列化的内容,我意识到这与类加载器无法修改现有类有关。
从我对 SO 和其他地方的阅读中,我意识到加载流类的 ClassLoader 必须被 GC 并替换,才能加载我的类的新版本。我知道如何做到这一点,但由于底层 RMI 运行时和它有自己的 RMIClassloader,情况似乎很复杂。
我的问题是:加载通过 RMI 参数接收的类的每个新版本的最简单方法是什么。理想情况下,我正在寻找一种方法,让每个远程调用都获得一个新的类加载器,并在返回时处理它。如果没有定制类加载器和 RMI 内部的复杂知识,这是否可行?
欢迎任何阅读材料或示例的指示!
编辑:这里是计算服务器的远程接口:
public interface ComputationEngine extends Remote {
public Object execute(Task t) throws RemoteException;
}
和“计算作业”接口,任务
:
public interface Task extends java.io.Serializable {
public Object compute();
}
I have a simple RMI 'compute' server application (similar to this) that accepts objects of some interface type from clients over RMI, executes the compute()
method of the received object and returns the result over RMI to the remote client. The jobs are 'one-offs' and there is no interaction between the different jobs or between objects of different jobs.
I would like to be able to modify classes and submit instances to the compute server for execution without constantly restarting the server JVM. However when a class that has been modified is submitted again as a parameter to a remote call it's method behaviour does not change (this occurs with anonymous classes also). I have been reading up about serialization and I realise that this is to do with the ClassLoader being unable to modify existing classes.
From my reading on SO and elsewhere I realise that somehow the ClassLoader that loaded the stream class must be GC'd and replaced in order to load a new version of my class. I have an idea how to do this but the situation seems complicated by the underlying RMI runtime and it having its own RMIClassloader.
My question is: What would be the easiest way to load each new version of a class received via RMI parameters. Ideally I'm looking for a way to have each remote call get a new ClassLoader and to dispose of it upon return. Is this feasible to do without an intricate knowledge of customised ClassLoaders and the internals of RMI?
Any pointers to reading materials or examples welcome!
Edit: here is the compute server's remote interface:
public interface ComputationEngine extends Remote {
public Object execute(Task t) throws RemoteException;
}
and the 'compute job' interface, Task
:
public interface Task extends java.io.Serializable {
public Object compute();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
唯一的方法是当您想要更改类时有一个新的类加载器。
如何利用 URLClassLoader 并通过 URL 提供代码?
我在我的一个项目中使用它来在 jar 文件更改时更新 API。看看这里:
http://code.google.com/p/open-forum/source/browse/trunk/Wiki/org/one/stone/soup/wiki/jar/manager/JarManager.java
第 184+ 行
检查您的电子邮件:-)
The only way to this is to have a new ClassLoader when you want to change a Class.
How about making use of the URLClassLoader and making the code available from a URL
I use it in one of my projects to update APIs when the jar file changes. Take a look here:
http://code.google.com/p/open-forum/source/browse/trunk/Wiki/org/one/stone/soup/wiki/jar/manager/JarManager.java
Line 184+
Check your emails :-)
这并没有真正回答您的问题,但也许可以将部分类更改为数据而不是实际的类。使用
Map
而不是字段等。您的类会少得多,并且您的代码可能也会更简单。This isn't really answering your question, but it might be possible to make changing part of your classes into data instead of the actual class. Use a
Map
instead of fields, etc. You'd have a lot fewer classes floating around, and your code would probably be simpler too.