【问题标题】:Are java RMI remote objects (server) singleton?java RMI远程对象(服务器)是单例吗?
【发布时间】:2014-09-12 18:24:57
【问题描述】:

我已经使用 java RMI 有一段时间了,但我不知道 RMI 远程存根(在服务器端)是否是单例的?我问的原因是:

让我们假设调用链中较低的 RMI 实现方法之一具有同步方法。如果由于某种原因同步方法中的逻辑混乱(或挂起),将来的 RMI 调用(来自客户端)在尝试访问该同步方法时也会挂起。仅当 RMI 存根将成为单例时,这才成立。如果在每次来自客户端的远程调用时在服务器端创建一个新对象,这将不是问题,因为方法是从不同的对象调用的,同步方法将不再是问题。

长话短说。我试图了解 JVM 如何在服务器端内部维护 rmi 远程对象以及它们是否是单例的。我尝试了许多不同的 javadocs,但他们没有在任何地方明确提及这一点。

感谢所有帮助!

编辑 基于一些问题和 cmets,我正在细化这个问题:我真正的问题是,服务器端的 RMI 是否碰巧根据您导出和注册的对象保留某种对象池?您可以绑定多个具有相同名称的相同类型的对象(有点模拟一个对象池,RMI 可以在其中为我提供我注册的任何对象)或者为了拥有同一个对象的多个实例,我将不得不用不同的名字注册它们

【问题讨论】:

    标签: java spring rmi remoteobject


    【解决方案1】:

    首先,“存根”是客户端的概念,服务器上没有存根。

    至于远程对象本身,RMI 系统不会为您实例化对象,由您自己创建实例并导出它们。您创建对象的一个​​实例,导出该对象,然后将其绑定到注册表中以特定名称。从注册表中的相同名称获取的客户端存根上的所有调用最终将在服务器上的相同对象处结束。

    你能绑定多个同类型的同名对象吗(有点模拟一个对象池,RMI可以给我任何我注册的对象)

    不可以,您只能在给定名称下绑定注册表中的一个对象。但是您绑定的对象本身可以是您自己的对象池的代理,例如使用Spring AOP CommonsPoolTargetSource 机制。

    【讨论】:

    • 您可以创建任意数量的实例 S。因此,它们根本不是单例。
    • @Ian Roberts:所以你的意思是,如果我实例化同一个类的多个对象,导出这些对象并用不同的名称将它们绑定到注册表中,它会起作用..我想我明白了那部分。但我想我真正的问题是服务器端的 RMI 是否碰巧根据您创建的对象保留某种对象池? (我想我也会用这个来更新我的问题)
    • @EJP 我试图表达的观点与您的相同——RMI 基础架构本身不会创建任何远程对象,它只是将调用路由到您选择导出的任何对象。如果要在注册表中绑定由服务器端对象池支持的对象,则由您自己进行池化,并使用合适的代理对象作为您在注册表中绑定的(单个)远程对象在那个名字下。在这方面,远程对象与本地对象没有什么不同。
    • 我在评论你现在已经删除的“他们是单身人士”这个词。
    • 我对整个事情的运作方式有了更好的了解。多谢你们!感谢您的帮助!
    【解决方案2】:

    存根不是单例,但您的问题实际上是关于服务器端对象的。它们也不是单例,除非您自己以这种方式实现它们。 RMI 对此不做任何事情。

    编辑基于一些问题和 cmets,我正在完善这个问题:我真正的问题是,服务器端的 RMI 是否碰巧根据您导出和注册的对象保留某种对象池?

    没有。

    可以绑定多个同类型的同名对象

    没有。

    我必须用不同的名字注册他们

    您根本不必注册它们。您需要一个绑定到注册表的单例远程对象:将其视为进一步远程对象的工厂方法,这些远程对象作为其远程方法的结果返回。例如,远程登录对象绑定在注册表中,并且有一个login() 方法,该方法返回一个远程会话对象,每次登录一个新对象,并具有自己的 API。

    【讨论】:

    • 那么它是如何工作的呢?如果我注册多个具有相同名称的服务器端对象(相同对象),它将是多个对象而不是一个单例?还是我必须注册多个不同名称的服务器端对象(同一个实现类)?
    • 远程对象只有在绑定到注册表时才有名称。这只是获取它们的一种方式。您还可以将它们作为远程方法的结果返回。例如考虑一个远程会话对象。每个客户都有一个,你会从某种登录对象返回它们,每个登录请求一个新的。
    【解决方案3】:

    RMI 它基于代理设计模式。

    看看here是怎么说的

    RMI 服务器是一个创建大量远程对象的应用程序。 RMI 服务器负责:

    1. 创建远程对象的实例(例如 CarImpl instance = new CarImpl());
    2. 导出远程对象;
    3. 将远程对象的实例绑定到 RMI 注册表。

    【讨论】:

    • 不回答问题。
    【解决方案4】:

    来自 Java 文档:

    http://docs.oracle.com/javase/7/docs/platform/rmi/spec/rmi-arch3.html

    由 RMI 运行时分派给远程对象的方法 实现可能会也可能不会在单独的线程中执行。 RMI 运行时不保证映射远程对象 对线程的调用。由于远程方法调用相同 远程对象可以同时执行,远程对象实现 需要确保其实现是线程安全的。

    是的,服务器端方法已同步。该实现是特定于平台的。你不能假设任何关于线程的事情。而且您当然不能假设远程对象是否是单例。

    此外,查看远程对象激活可能会很有用:

    http://docstore.mik.ua/orelly/java-ent/jenut/ch03_06.htm

    http://docs.oracle.com/javase/7/docs/api/java/rmi/activation/package-summary.html

    【讨论】:

    • 服务器端方法不同步,除非你自己同步。
    猜你喜欢
    • 2018-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多