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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11187548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 04:08:35  来源:igfitidea点击:

is it possible to pass by reference in RMI?

javarmi

提问by MBZ

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. e.g.: this oneand this one

他们中的一些人说在 RMI 中通过引用传递变量是不可能的。例如:这个这个

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

而其他人则说这是可能的。例如: 这个这个这个

can anyone clear this up please? :)

任何人都可以解决这个问题吗?:)

采纳答案by helios

Important note:if pass by referencemeans modifying argument value inside the method and change original variable in caller, you can't. If what you want to do is passing a copyof 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 对象。在这种情况下,将通过副本传递 RMI 存根。

RMI passes arguments and return values two ways:

RMI 通过两种方式传递参数和返回值:

  1. copy the full object
  2. send a remotereference (it has to be remote if its a reference!).
  1. 复制完整对象
  2. 发送一个远程引用(如果它是一个引用,它必须是远程的!)。

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.

猜猜我们有一个服务。它是一个 RMI 对象,通过 RMI 注册表发布,因此客户端可以访问它。客户端可以调用一个方法(创建一些东西),服务想要返回对新创建的对象的引用。不是序列化副本,而是对服务器内存空间中创建的对象的引用。

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
}

回答by user207421

Of your references:

您的参考资料:

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

(1) 说 RMI 不支持通过引用传递。我同意。

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

(2) 说 RMI 不支持输入输出参数。我同意。

(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.

(3) 只是表现出按引用传递和按值传递引用之间的常见混淆。RMI 执行后者,就像 Java 的其余部分一样。

(4) is wrong.

(4) 错误。

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

(5) 只是简单的语无伦次。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 的按值引用的参数传递方法。

回答by user439407

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 无法访问 B 的内存*。

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. 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 使用标准的 Java 对象序列化机制来传递对象。作为远程对象引用的参数作为远程引用传递。如果方法的参数是原始类型或本地(非远程)对象,则将深层副本传递给服务器。返回值的处理方式相同,但方向不同。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 所说的。