The client program does not have immediate access to the
object on the server.
Instead, a lot of magic takes place:
The value returned by the call of
lookup
in the
CountClient
program is a reference to an object that is part of the client
program.
This object is a
stub
that acts as a proxy for the remote object.
When the client program calls a method,
say, it calls
stubCount.setCount(42),
then it is actually calling a method called
setCount of the stub.
This method knows nothing about how to set the
remote object's value to 42.
Instead, what it does is to transmit the required operation to
the server:
it does this by arranging for
the method and its
parameters
to be
marshalled
into a stream of bytes.
This marshalling makes use of
JDK 1.1.x's
object serialization.
Within the Java application running on the server,
there is the real object.
However, besides this real object there is also a
skeleton
object.
The skeleton has a method that arranges for
any incoming requests to be unmarshalled.
By this means,
it finds out what method is to be called and what arguments are
to be supplied to the call.
It then calls the appropriate method of the real object
with the appropriate arguments.
If the method being called returns some result, then the skeleton's method will get the result, serialize the result, and pass the bytes back to the client computer. The method in the stub will receive these bytes, de-serialize them, and return a value to the caller.
So besides the code that you write for the client and the server, you will also need code for the stub and the skeleton. Fortunately, RMI comes with a tool (called rmic) that will automatically generate the stub and skeleton files for you.