【问题标题】:Java RMI, making an object serializeable AND remoteJava RMI,使对象可序列化和远程
【发布时间】:2011-09-10 05:43:46
【问题描述】:

您可能会想,为什么要拥有一个既可远程又可序列化的对象。好吧,让我给你一些背景。

我正在构建一个空中交通管制系统(学校项目),它是分布式的,因此每个管制区都在自己的服务器上运行并与其他管制区通信。每个控制区都跟踪自己的飞机。

当一架飞机(在控制区 A 中飞行)在其边界附近 100 公里处时,它会作为远程对象传递到它附近的控制区(控制区 B)。这样控制区 B 可以看到飞机在哪里(通过定期询问它的位置),而它仍然由控制区 A 控制。

但是当飞机越过控制区 A 和 B 之间的边界时,控制区 B 应该跟踪飞机而不是控制区 A。所以我们想要序列化飞机并将其传递给 controlZone B。这就是我们的问题所在.

我可以使飞机远程和可序列化吗?

编辑:另外,我可以使用远程方法来复制飞机所需的字段,但我更喜欢序列化它。

【问题讨论】:

  • 如果飞机是可序列化的,为什么不把它传给离它一定距离的 Controlzone X,我不认为它也需要远程
  • 我需要它的位置每秒 20 次,我不想向 Controlzone A 询问序列化对象 20 次..
  • 问题是,RMI 系统应该如何决定何时序列化对象(即复制它)以及何时将其作为远程引用传递?
  • 您可以从 ControlZone A 请求一次,然后 A 和 B 都可以跟踪它的运动,直到它完全穿过 B。
  • 这行不通,因为飞机在 A 区时由 A 控制。所以如果我只是离开副本@B,它不会移动或改变方向。

标签: java serialization rmi


【解决方案1】:

您不必使您的对象成为 UnicastRemoteObject 的子类。

使用你的类,定义它来实现 Serializable 和你的 RMI api 接口,它本身应该实现 Remote。它不需要继承 java.lang.Object 以外的任何东西。

当您准备好远程调用您的对象时,请在其上调用静态 UnicastRemoteObject.exportObject() 方法。从那时起,您通过 RMI 返回到该对象的任何引用都将是可远程调用的。

当您想将对象传递到另一个服务器时,请在您的对象上调用 UnicastRemoteObject.unexportObject()。然后,当您通过 RMI 调用传递它时,您将传递该对象的序列化表示。

这样做的缺点是一旦您将其传递出去,您服务器上的对象将不再接受 RMI 调用。 unexportObject() 作为 RMI 调用接收者将其完全关闭。

如果您希望能够将一个对象作为 RMI 目标进行维护,并同时将其作为可序列化对象通过 RMI 传递,您需要使其可序列化并插入一个代理对象,该对象导出远程接口并且可以代表调用者与未导出的、可序列化的对象交谈。

当你想通过序列化传递底层对象时,你直接传递它。当你想传递一个远程可调用的引用时,你传递代理。

【讨论】:

    【解决方案2】:

    结果证明这个解决方案不正确。请参阅下面@EJP 的答案,了解使用单个实例执行此操作的唯一方法。

    【讨论】:

    • 不扩展 UnicastRemoteObject 实际上与它没有任何关系。看我的回答。
    • @EJP - 不扩展 UnicastRemoteObject 当然 does 与此有关。虽然当您 确实 扩展 UnicastRemoteObject(我不知道)时,它显然可以“某种”工作,但我认为我的解决方案要干净得多。
    • @jtahborn 不。如果您扩展 UnicastRemoteObject,您将免费获得“实现可序列化”。如果没有,您可以自己添加。没有其他区别。
    • @EJP - 我现在不确定你的论点是什么。基本上,如果您 扩展 UnicastRemoteObject,您将获得非常清晰的序列化和导出语义。如果你扩展它,序列化语义依赖于当前的导出状态,对我来说,这有点难看。
    • @jtahlborn 我的“论点”是你的句子以“诀窍是......”开头是无关紧要的。如果您扩展 UnicastRemoteObject,您将获得 Serializable,如果您不扩展,您可以自己添加它。它没有“技巧”。
    【解决方案3】:

    如果远程对象在作为远程方法参数或结果发送时未导出,则它会被序列化,而不是作为远程引用传递,前提是它实现了 Serializable 和 Remote。然后在接收器处导出。例如,UnicastRemoteObject 就是这样做的,因此从它派生的任何远程对象也是如此。这可用于移动远程代理。

    【讨论】:

    • 好吧,考虑到 Airplane 实例很可能在需要序列化和远程发送时被导出,我想我的解决方案是必要的。跨度>
    • @jtahlborn:如果不是,不是。这对我们没有任何帮助。
    【解决方案4】:

    看看UnicastRemoteObject 类。它通常用于 RMI 中的回调驱动编程,因此实现了RemoteSerializable。虽然您可能想重新审视您的逻辑,因为您现在拥有一个充当“远程服务器”的实体(飞机)。

    【讨论】:

    • 不是真的,你能说出你为什么认为它像一个远程服务器吗?
    • 请阅读UnicastRemoteObject 的文档,特别是它的超类RemoteServer 以获得更多解释。当您想从 JVM 导出“对象”并且此单播对象上的所有更改/方法调用都会影响原始对象而不是影响副本时,通常会使用此类,这通常在您的对象可序列化但不是远程时发生。
    • 我知道这一点,因为我的 OP 声明我首先想要这种行为。但是当飞机经过时,我希望它传递一个副本而不是一个远程 obj
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2011-11-21
    相关资源
    最近更新 更多