I'm trying to implement a middle-ware for group communication in a distributed system using Java RMI.
In there, I need to send an object to server and modify it. So that changes should be reflected in the client side.
For example, I will give the most common tutorial in Oracle web site.
X.java
public class X implements Serializable, Remote{
public int x; // defined as public, just be simple.
}
Hello.java
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
String sayHello(X c) throws RemoteException;
}
Server.java
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
public class Server implements Hello {
public Server() {
}
public String sayHello(X c) {
c.x = 10;
return "Hello, world!";
}
public static void main(String args[]) {
try {
Server obj = new Server();
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0);
LocateRegistry.createRegistry(1099);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.getRegistry();
registry.bind("Hello", stub);
System.err.println("Server ready");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
Client.java
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public int x = 4;
private Client() {
}
public static void main(String[] args) {
String host = (args.length < 1) ? null : args[0];
try {
Registry registry = LocateRegistry.getRegistry(host);
Hello stub = (Hello) registry.lookup("Hello");
X x = new X();
String response = stub.sayHello(x);
System.out.println("response: " + x.x);
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
My problem is, even if I update the value for x in object c in the server side, it is not reflected to the client side. I simply could use the return to get the updated value, but I'm planning to use this method to implement a multi-cast function for the server.
Can anyone explain why? And If I need to do so, what is the way of doing it?
解决方案
When you use RMI you are having 2 (or more) java virtual machines involved in a given computation, so when you create an object at the client side and call a method on the server passing this object as an argument the state of the objectis serialized and sent through the network. On the server side a new object of the same class is created and the state is set on it, but it is a different object with the same values in it. Operating on this clone won't reflect on the original object that is still residing on the source virtual machine.
You would have to use a rmiregistry on each machine that runs a virtual machine and registering each object to expose it (this is a distributed solution) or you could concentrate all the data objects on the machine that has the rmiregistry (this is a centralized solution, since all objects are on the same machine).
Cheers