Re: Does unexport() on UnicaseRemoteObject release the port?
Peter Jones - JavaSoft East <[email protected]>
| Newsgroups | gmane.comp.java.sun.rmi |
|---|---|
| Message-ID | <20050728051735.GA850@east> |
> Peter,
> I'm a colleague of Charlie's. He was posting on my behalf, but I have
> now joined the list. Thanks for your help so far.
> You asked for some code. I have recreated the problem in a simple MBean.
> When I redeploy the MBean, RMI calls createSocket even though the
> ServerSocket from the original deployment is still in memory and bound
> to port 1000. This call throws an exception, of course, because the
> port is in use.
> When I don't use a custom RMIServerSocketFactory, everything works OK.
That server socket factory class's equals implementation seems plenty
promiscuous[1], so my best guess is that the RMI implementation is not
considering successive instances of it to be equal because each
instance's class is getting defined by a different class loader, for
each "deployment"? (You could verify this by logging its class loader
in its static initializer, or something like that.) When checking for
socket factory equivalence, the RMI implementation first requires two
factories' classes to be identical (meaning same name and defining
class loader) before invoking Object.equals on one of them, in order
to guard against use of a malicious socket factory class to share
resources of a privileged one by claiming equality to it. If this is
indeed the case, one solution could be to arrange for the server
socket factory class to be loadable from some shared class loader,
like in the VM's class path or an extension directory.
Alternatively, if when unexporting your remote object(s) you don't
need to worry about their particular server socket factory instance
ever being used again, you could work around 4457683 with a server
socket factory hook much simpler than the one I posted last week[2]:
save a reference to the server socket factory that was used to export
the remote object(s), and when unexporting them, also invoke a method
on the saved factory that causes it to close the server socket(s) that
it has created. (That approach could then result in leaking an accept
thread per server socket closed-- the fact that an RMI accept thread
doesn't automatically terminate when the server socket has been
externally closed is a separate bug-- but if necessary that could be
addressed with a custom RMIFailureHandler...)
-- Peter
[1] overly so, I presume because this is test code; a real ssf.equals
implementation should at least do something like
return other != null && getClass() == other.getClass();
[2] http://archives.java.sun.com/cgi-bin/wa?A2=ind0507&L=rmi-users&P=4036
> public class Example implements ExampleMBean{
> private ExampleService svc;
>
> public void start() throws Exception {
> try {
> LocateRegistry.createRegistry(999);
> } catch (ExportException e) {
> // happens when redeployed
> }
> svc = new ExampleServiceImpl();
> UnicastRemoteObject.exportObject(svc, 1000, null, new ssf());
> Naming.bind("//localhost:999/example", svc);
> }
>
> public void stop() throws Exception {
> Naming.unbind("//localhost:999/example");
> UnicastRemoteObject.unexportObject(svc, true);
> }
>
> private static class ssf implements RMIServerSocketFactory, Serializable{
>
> public ServerSocket createServerSocket(int port) throws IOException {
> return new ServerSocket(port);
> }
> @Override
> public boolean equals(Object other){
> return true;
> }
>
> @Override
> public int hashCode(){
> return 1;
> }
> }
> }
===========================================================================
To unsubscribe, send email to [email protected] and include in the body
of the message "signoff RMI-USERS". For general help, send email to
[email protected] and include in the body of the message "help".
For a list of frequently asked RMI questions please refer to:
http://java.sun.com/j2se/1.3/docs/guide/rmi/faq.html
To view past RMI-USERS postings, please see:
http://archives.java.sun.com/archives/rmi-users.html