The story of the RMI stubs
After many years since the original release, Sun realized that the stub and skeleton files are not really needed for RMI programs.
Leaving skeletons aside (not needed since JDK 1.2) let's talk about stubs.
The RMI stubs are the "client side" component that pretend to be local "server side" classes, but actually delegate all their methods to the server.
The RMI stubs only depend on the remote interfaces implemented by the remote class and they don't depend on the implementation of the remote class. The only reason why the 'rmic' compiler needs the remote class implementation is to find out what remote interfaces it implements.
(I will try to write more on how it works later, meanwhile all the details can be found in Sun's RMI reference documents).
Are RMI stubs obsolete?
So if the stubs only depend on the remote interfaces and not on the remote class implementation, the stubs always look pretty much the same. Generating them on the server side and loading them on the client side is redundant. Indeed, in Java 5.0 a Proxy is used to generate the stubs on the fly on the client side. The RMI implementation know exactly which interfaces the remote object implements and using the Proxy class it can create the same code that delegates method calls to the server machine at runtime, which it does.
Why generate stubs then?
Relying on dynamic stubs generation has some restrictions. First of all, if you have any interaction with pre 5.0 code, you must use stubs (dynamic proxies for RMI are Java 5.0 feature). Another reason to generate stubs is for checking your implementation. For example, every method in the remote interface must delcare throwing a RemoteException.
The RMI compiler (rmic) can detect such problem and issue an error. You detect the error at compile time and you're happy.
If the RMI compiler isn't used, your user will get the following error when your server tries to bind a remote object to the registry:
- Code: Select all
Something wrong happended on the remote end
java.rmi.server.ExportException: remote object implements illegal remote interface; nested exception is:
java.lang.IllegalArgumentException: illegal remote method encountered: public abstract java.lang.String demo.rmi.printers.server.RemotePrinter.getPrinterStatus()
at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:171)
at java.rmi.server.UnicastRemoteObject.exportObject(UnicastRemoteObject.java:293)
...........
Caused by: java.lang.IllegalArgumentException: illegal remote method encountered: public abstract public abstract java.lang.String demo.rmi.printers.server.RemotePrinter.getPrinterStatus()
The user won't be happy. So, if you want to discover this error earlier, generating the RMI stubs will help to achieve it.