The implementation class associated with the MPJSlave interface normally behaves as follows (schematically):
public class MPJSlaveImpl extends UnicastRemoteObject {
public static void main(String args []) {
int slaveID = Integer.parseInt(args [0]) ;
String masterPort = args [1] ;
MPJService master =
(MPJService) Naming.lookup("rmi://localhost:" + args [1] +
"/MPJService") ;
master.addSlave(int slaveID, int new MPJSlaveImpl()) ;
}
public runTask(MPJApplication task, String [] args, ...)
throws RemoteException {
... create default communicator, `world'
task.main(world, args) ;
}
}
The main method creates a remote object and ``registers''
it with its daemon by calling a remote method addSlave on the master.
Later the client calls back with the runTask method, passing
an instance of the actual user class. Because this is a serializable
object it is passed by value to the remote runTask method.
Importantly, the byte code for the user class will be loaded by RMIClassLoader from the code-base specified in the serialized object.
As discussed below, this will be the URL of a process serving a (typically
very much stripped-down) subset of the HTTP protocol.
Hence, using the dynamic class-loading mechanisms provided as standard in RMI, we ensure that all user code is automatically available to the remote host.