简体   繁体   English

是否可以通过RMI中的引用传递?

[英]is it possible to pass by reference in RMI?

I have read various articles about passing variables around using RMI. 我已经阅读了有关使用RMI传递变量的各种文章。

Some of them say that it is impossible to pass variables by references in RMI. 他们中的一些人说,不可能通过RMI中的引用传递变量。 eg: this one and this one 例如: 这一个这一个

While others says that it is possible. 而其他人说这是可能的。 eg: this one , this one and this one 例如: 这一个这一个这一个

can anyone clear this up please? 任何人都可以清楚这一点吗? :) :)

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. 但它必须是一个RMI对象。 In that case a RMI stub will be passed by copy. 在这种情况下,RMI存根将通过副本传递。

RMI passes arguments and return values two ways: RMI以两种方式传递参数和返回值:

  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. 它是一个RMI对象,通过RMI注册表发布,因此可以访问客户端。 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 创建MyService的实现并发布它

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 然后,一些RMI客户端可以获得它的引用

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. 并且对服务对象的引用可以获得对其他RMI对象的引用。

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. 在此示例中,方法参数是序列化的(它应该是Serializable类),而返回的对象是对服务器中创建的对象的RMI引用。

The implementation of createX(...) could be: createX(...)的实现可能是:

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
}

Of your references: 你的参考资料:

(1) says RMI does not support pass by reference. (1)说RMI不支持通过引用传递。 I agree. 我同意。

(2) says RMI does not support in-out parameters. (2)表示RMI不支持进出参数。 I agree. 我同意。

(3) just exhibits the usual confusion between pass by reference and passing references by value. (3)只是表现出通过引用传递和通过值传递引用之间的通常混淆。 RMI does the latter, just like the rest of Java. RMI就像Java的其他部分一样完成后者。

(4) is wrong. (4)错了。

(5) is just plain incoherent. (5)只是简单的语无伦次。 There is no pass-by-reference in RMI. 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. 除了额外可能的故障模式之外,RMI的远程“按值引用”在本质上与Java的本地“按值引用”在语义上没有区别。

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. 您所读到的内容的含义是,对于非远程引用,RMI对象参数和结果通过通过对象序列化传递,而不是通过Java的参数传递方法逐个值传递。

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*. 但是将内存引用从计算机A传递到计算机B是没有意义的,A无法访问Bs内存*。

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. 但是,RMI允许您获取对远程对象的“引用”,但这不完全相同,并且必须提前请求,将您的一个对象传递给服务器将产生副本。

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

RMI uses the standard Java object serialization mechanism to pass objects. RMI使用标准Java对象序列化机制来传递对象。 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. RMI允许您传递和返回本地对象的完整对象图以及对远程对象的引用。

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. *技术上在一些大规模的分布式共享内存系统中你可以,但我怀疑这是OP正在谈论的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM