Stub Class not found - only when using port-less exportObject()

Hello,

I have a case ofjava.rmi.StubNotFoundException: Stub class not found that I tracked down to being somewhat related to the way I export my object. I am relieved I have a way to workaround this, but I don't understand why the API seems to work in a way that is not documented, and I am considerting openeing a bug for this.

Here are the details:

My service interface:

publicinterface MyServicesextends Remote{ ...}

My server implementation:

publicclass MyServerimplements MyServices{...}

Note that I am in Java 6, so there is no need to run anrmic compiler on the Remote interface to generate a stub class, and no need for MyServer to extend UnicastRemoteObject.

Eventually here is my main method:

server =new MyServer();

try{

// JDK javadoc says this will "Export the remote object (...) using an anonymous port.

MyServices serverStub =

(MyServices)UnicastRemoteObject.exportObject(server);

}

catch(Exception e){

Log.fatal(THIS_CLASS,"Impossible d'exporter le serveur", e);

}

This latter causes an exception:java.rmi.StubNotFoundException: Stub class not found.

I changed the exportObject call to:

MyServices serverStub =

(MyServices)UnicastRemoteObject.exportObject(server, 0);// or 1024, or whatever value I tried

And then I don't have the exception.

The javadoc forexportObject(Remote obj, int port) says that it "Exports the remote object (...) using the particular supplied port.".

What I don't get is what it has to do with finding the stub class.

Digging depeer (just before sending this post), I noticed that the class-level javadoc for UnicastRemoteObject mentions that:

for "UnicastRemoteObject.exportObject(Remote) method, a stub class (typically pregenerated from the remote object's class using the rmic tool) is loaded and an instance of that stub class is constructed as follows (..)[algorithm skipped].",[whereas] For all other means of exporting (...) aProxy instance is constructed (...)with a RemoteObjectInvocationHandler instance constructed with a RemoteRef."

In other words, a Remote class can only be "dynamically exported" if you specify a port.

To end mixing me up, the Java tutorial explicitly says "It is common to use the value zero [for the port argument of exportObject(..)], which specifies the use of an anonymous port. The actual port will then be chosen at runtime by RMI or the underlying operating system".

Why are dynamic stubs available only when specifying a port, even if the port is 0, which means, "whatever port"?

Do you think this is a bug?

[3355 byte] By [jdupreza] at [2007-11-26 22:17:03]
# 1

It's a binary compatibility issue.

UnicastRemoteObject.exportObject(Remote) is specified to return a RemoteStub so it has to return a generated stub (which extend RemoteStub).

UnicastRemoteObject.exportObject(Remote, int port) is specified to return a Remote, which can be either a generated stub (extending RemoteStub) or a dynamic stub (implementing one or more Remote interfaces).

It's not a bug as it's documented behaviour, and it can't be fixed.

ejpa at 2007-7-10 11:10:46 > top of Java-index,Core,Core APIs...
# 2

> It's a binary compatibility issue.

Right, I hadn't noticed that the methods had different return types.

Thanks for your answer, that puts the finger on a very interesting innards of the JVM.

I award you the points, but I disagree with the details.

First, I find it not very intuitive that the method have the same name, and that the different semantics of the return types are hidden behind a parameter that has nothing to do with this difference.

Second, it was technically harder, and possibly not worth it, but not infeasible, to generate a dynamic proxy subclassing RemoteStub.

Or course the built-in Proxy class can only dynamically implement an interface, but other techniques exist for such dynamic implementation of abstract classes, though they involve dynamic generation of bytecode.

> It's not a bug as it's documented behaviour, and it

> can't be fixed.

It's not a bug, right, but I deem the documentation is misleading, though not wrong strictly speaking.

jdupreza at 2007-7-10 11:10:46 > top of Java-index,Core,Core APIs...
# 3

> First, I find it not very intuitive that the method

> have the same name, and that the different semantics

> of the return types are hidden behind a parameter

> that has nothing to do with this difference.

Agreed but binary compatibility is binary compatibilty.

> Second, it was technically harder, and possibly not

> worth it, but not infeasible, to generate a dynamic

> proxy subclassing RemoteStub.

Dynamic proxies extend java.lang.reflect.Proxy so they can't extend anything else.

> Or course the built-in Proxy class can only

> dynamically implement an interface, but other

> techniques exist for such dynamic implementation of

> abstract classes, though they involve dynamic

> generation of bytecode.

None that are used by the JDK. There are all kinds of security issues raised by this suggestion.

> It's not a bug, right, but I deem the documentation

> is misleading, though not wrong strictly speaking.

http://java.sun.com/j2se/1.5.0/docs/guide/rmi/relnotes.html

ejpa at 2007-7-10 11:10:46 > top of Java-index,Core,Core APIs...