is it possible to pass by reference in RMI?
Asked Answered
L

3

11

I have read various articles about passing variables around using RMI.

Some of them say that it is impossible to pass variables by references in RMI. e.g.: this one and this one

While others says that it is possible. e.g.: this one, this one and this one

can anyone clear this up please? :)

Lento answered 25/6, 2012 at 10:26 Comment(0)
A
7

Important note: if pass by reference means modifying argument value inside the method and change original variable in caller, you can't. If what you want to do is passing a copy of a reference to an object, to allow the method interact with some object of yours... yes you can. The answer explores that second option.

Yes. But it has to be an RMI object. In that case a RMI stub will be passed by copy.

RMI passes arguments and return values two ways:

  1. copy the full object
  2. send a remote reference (it has to be remote if its a reference!).

Sample

Guess we have a Service. It's a RMI object, published through the RMI registry, so it's accesible to clients. Client can call a method on it (to create something) and the service wants to return a reference to that newly created object. Not a serialized copy but a reference to the created object in server memory space.

import java.rmi.Remote;
import java.rmi.RemoteException;

// normally published object
public interface MyService extends Remote
{
    // creates something and return a "handle" to it
    public MyHandle createX(SomeSerializableObj param1) throws RemoteException;
}

// interface for object that the service will return a reference to...
public interface MyHandle extends Remote
{
    void doOne();
    void doTwo();
}

In this example you could:

Create an implementation of MyService and publish it

Registry registry = LocateRegistry.createRegistry(port);
MyService stub = (MyService) UnicastRemoteObject.exportObject(server, 0);
registry.bind("myService", stub);`

and then, some RMI client could get a reference to it

Registry registry = LocateRegistry.getRegistry(server, port);
MyService serv1 = (MyService) registry.lookup("myService");

and with a reference to the service object could obtain a reference to other RMI object.

MyHandle handle1 = serv1.createX(...);
handle1.doOne()

In this example the method argument is serialized (it should be a Serializable class) while the returned object is a RMI reference to an object created in the server.

The implementation of createX(...) could be:

public MyHandle createX(...) {
   MyHandle handle = new MyHandleImpl(); // create an implementation
   createdHandlers.add(handle); // add it to some structure (just a sample)
   return handle; // return the implementation. RMI will send to client a RMI reference to this very instance
}
Ahola answered 25/6, 2012 at 10:28 Comment(4)
thanks :) but I don't quite get your answer :( can you provide an example please? :)Lento
@Lento It seems to me that he has already given you an example, but this is just another example of a reference being passed by value. It is not pass by reference at all. Changing the value of the reference in the callee does not change it in the caller. Downvote.Harber
I understand what you say @EJP. It depends on what MBZ is asking. If she/he wants to send some kind of handle to a remote object then the answer is what's needed. If you want "pass by reference" as defined in procedural languages, of course not. I think it's the first option. Anyway I'll add a clarification.Ahola
Important note: 'pass by reference' does mean that.Harber
H
3

Of your references:

(1) says RMI does not support pass by reference. I agree.

(2) says RMI does not support in-out parameters. I agree.

(3) just exhibits the usual confusion between pass by reference and passing references by value. RMI does the latter, just like the rest of Java.

(4) is wrong.

(5) is just plain incoherent. There is no pass-by-reference in RMI.

RMI's remote 'references-by-value' is essentially no different semantically from Java's local 'references-by-value', apart from the additional possible failure modes.

The meaning of what you have read is that for non-remote references, RMI object arguments and results are passed by value, via Object Serialization, rather than by Java's argument passing method of reference-by-value.

Harber answered 25/6, 2012 at 23:12 Comment(0)
P
0

In the truest sense of the word no, you cannot.

When you pass something by "reference" what you are really doing is passing a pointer to a location in memory. This works perfectly when the caller and callee are the same process, they have access to the exact same heap. But passing a memory reference from computer A to computer B is meaningless, A cannot access Bs memory*.

However RMI lets you get "references" to remote objects, but this isnt quite the same, and it has to be requested ahead of time, passing one of your objects to the server will result in a copy.

Straight from the horses mouth(http://www.oracle.com/technetwork/java/javase/tech/index-jsp-138781.html#3)

RMI uses the standard Java object serialization mechanism to pass objects. Arguments that are references to remote objects are passed as remote references. If an argument to a method is a primitive type or a local (non-remote) object, a deep copy is passed to the server. Return values are handled in the same way, but in the other direction. RMI lets you pass and return full object graphs for local objects and references to remote objects.

You can pass around remote objects by reference, but you cannot pass local objects back to the server as references.

*Technically in some large-scale distributed shared memory system you could, but I doubt that is what the OP is talking about.

Palawan answered 26/6, 2012 at 1:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.