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

时间:2012-06-25 10:26:40

标签: java rmi

我已阅读过有关使用RMI传递变量的各种文章。

他们中的一些人说不可能通过RMI中的引用传递变量。例如:this onethis one

虽然其他人说这是可能的。例如。: this onethis onethis one

有人可以清楚这一点吗? :)

3 个答案:

答案 0 :(得分:5)

重要说明:如果按引用传递意味着修改方法内的参数值并更改调用者中的原始变量,则不能。如果您要做的是将对引用的副本传递给对象,则允许该方法与您的某个对象进行交互...是的,您可以。答案探讨了第二种选择。

是。但它必须是一个RMI对象。在这种情况下,RMI存根将通过副本传递。

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

  1. 复制整个对象
  2. 发送远程引用(如果是引用,则必须是远程引用!)。
  3. <强>示例

    猜猜我们有服务。它是一个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();
    }
    

    在这个例子中你可以:

    创建MyService的实现并将其发布

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

    然后,一些RMI客户端可以获得对它的引用

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

    并且对服务对象的引用可以获取对其他RMI对象的引用。

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

    在此示例中,方法参数是序列化的(它应该是Serializable类) 返回的对象是对服务器中创建的对象的RMI引用。

    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
    }
    

答案 1 :(得分:3)

您的参考资料:

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

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

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

(4)错了。

(5)只是简单的语无伦次。 RMI中没有传递参考。

除了可能的其他故障模式之外,RMI的远程“按值引用”在语义上与Java的本地“按值引用”基本没有区别。

您所读到的内容的含义是,对于非远程引用,RMI对象参数和结果由 value,通过Object Serialization传递,而不是通过Java的参数传递方法引用 - 值。

答案 2 :(得分:0)

在最真实的意义上,你不能。

当您通过“引用”传递某些内容时,您实际在做的是将指针传递给内存中的某个位置。当调用者和被调用者是相同的进程时,它可以完美地工作,他们可以访问完全相同的堆。但是将内存引用从计算机A传递到计算机B是没有意义的,A无法访问Bs内存*。

然而,RMI允许您获取远程对象的“引用”,但这不完全相同,并且必须提前请求,将您的一个对象传递给服务器将产生副本。

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

  

RMI使用标准Java对象序列化机制来传递对象。引用远程对象的参数作为远程引用传递。如果方法的参数是基本类型或本地(非远程)对象,则会将深层副本传递给服务器。返回值以相同的方式处理,但在另一个方向上。 RMI允许您传递和返回本地对象的完整对象图以及对远程对象的引用。

您可以通过引用传递远程对象,但不能将本地对象作为引用传递回服务器。

*技术上可以在一些大规模的分布式共享内存系统中使用,但我怀疑OP是在谈论什么。