Name: rm29839 Date: 03/17/98
Consider a Java applications as RMI clients which
must support callbacks for use by servers. The
'rmiregistry' may not be running on the client
systems. Therefore, we attempt to create a registry via
java.rmi.registry.LocateRegistry.createRegistry(int port).
Thus, each invokation of the application has its
own unique registry available for callbacks, without
having to run 'rmiregistry' on the client systems.
Normally this works just fine. The registry is
created, and the client application can register
its callback in the registry, and pass a reference
for the callback to the servers. The callbacks
work just great.
However, if the port at which the client attempts
to create the registry is already in use, an
exception is thrown. This is as it should be.
Now, additional attempts to create a registry are
tried by incrementing the port number to find an
unused port. However, all of these second (and later)
attempts fail with a java.rmi.serverExportException
with text "Object ID already in use".
This has problem exists at least in the 1.1.5 and
1.2beta2 JDK on Windows NT and the 1.1.4 JDK on
Solaris.
The following simple client program duplicates the
problem:
import java.net.*;
import java.rmi.*;
import java.rmi.registry.*;
public class bad
{
public static void main(String args[])
{
final int port = 5555;
// Create a socket at particular port.
try
{
ServerSocket sock = new ServerSocket(port);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
// Attempt to create a socket at the same port. This should fail.
System.out.println("--------------------------------------");
System.out.println("First attempt to create registry.");
try
{
LocateRegistry.createRegistry(port);
}
catch (Exception e)
{
System.out.println("Whoops, port is in use!");
System.out.println(e.getMessage());
}
// Attempt to create a socket at the next available port.
System.out.println("--------------------------------------");
System.out.println("Second attempt to create registry.");
try
{
LocateRegistry.createRegistry(port + 1);
}
catch (Exception e)
{
System.out.println("Hmmm... not good!");
e.printStackTrace();
}
System.out.println("--------------------------------------");
System.exit(0);
}
}
The output is:
--------------------------------------
First attempt to create registry.
Whoops, port is in use!
Port already in use: 5555; nested exception is:
java.net.BindException: Address already in use
--------------------------------------
Second attempt to create registry.
Hmmm... not good!
java.rmi.server.ExportException: Object ID already in use
at sun.rmi.transport.ObjectTable.putTarget(ObjectTable.java:81)
at sun.rmi.transport.Transport.exportObject(Transport.java:72)
at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:173)
at sun.rmi.transport.tcp.TCPEndpoint.exportObject(TCPEndpoint.java:222)
at sun.rmi.transport.LiveRef.exportObject(LiveRef.java:114)
at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:92)
at sun.rmi.registry.RegistryImpl.setup(RegistryImpl.java:88)
at sun.rmi.registry.RegistryImpl.<init>(RegistryImpl.java:74)
at sun.rmi.registry.RegistryHandler.registryImpl(RegistryHandler.java:65)
at java.rmi.registry.LocateRegistry.createRegistry(LocateRegistry.java:131)
at bad.main(bad.java:41)
--------------------------------------
My guess is that proper cleanup of the registry
object does not occur during exceptions. Some
reference to the original failed registry creation
is still stored in some internal table, causing
the second and all subsequent attempts to create
a registry fail. This "object ID" needs to be
cleaned up during a failed creation attempt.
(Review ID: 26291)
======================================================================