带有远程参数的 Java RMI 调用失败

标签 java rmi

我从 RMI 注册中心获得一个远程引用;让我们称它为 s。现在,s 是(接口(interface))类型 S,它提供了一个方法 m(A, B, int)

在客户端,我有 AB 的实现,它们都扩展了 UnicastRemoteObject(因此自动导出)。分别考虑实例 ab

现在我调用 m(a, b, 0)。它编译,但在运行时失败,非常无信息

java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
at sun.rmi.transport.Transport$1.run(Transport.java:159)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy0.m(Unknown Source)
[... application specific sites]

遗憾的是,NativeMethodAccessorImpl.invoke0 是 native 实现的,无法检查。所以,我完全不知所措。显然,类型匹配,否则原始代码应该无法编译,对吧?

这可能是什么原因?

编辑:我们使用 Java 6。该错误可以在 Ubuntu 11.04 32 位、Ubuntu 10.10 64 位和 Windows 7 32 位上重现。

编辑 2:我在 S 上实现了一些虚拟方法来测试各个参数。事实证明,s.n()s.t0(b)s.t1(0) 按预期工作;只有 s.t2(a) 失败了。这意味着我实现 A 的方式有问题,不是吗?

AB 之间唯一显着的区别(当然除了实际内容之外)是 A 是一个扩展 的类>UnicastRemoteObject 并遵循远程接口(interface)的约定,但不实现可区分的远程接口(interface)。 B 是我传递的远程接口(interface)实现。

最佳答案

事实证明,我在第二次编辑中提供的信息至关重要。

您只能将显式实现扩展Remote 接口(interface)的类的实例导出/用作远程对象实例。特别是, 有一个扩展 UnicastRemoteObject 的类是不够的——即使那个实现了 Remote!在那种情况下,一切都可以正常编译和导出,但实际上远程传递对象会导致上述异常。

我想为不存在远程接口(interface)的远程类型创建骨架/ stub 会以某种方式失败。应该有更好的治疗方法,但是很好。

编辑:澄清一下:UnicastRemoteObject 实现Remote。现在,有类似的东西

class A extends UnicastRemoteObject { void m() throws RemoteException {} }

是不够的,即使 A 间接实现了 Remote。您将能够实例化(即导出),但不能将其作为 A 远程传递。

你需要做的

interface B extends Remote { void n() throws RemoteException; }
class BImpl extends UnicastRemoteObject implements B { void n() throws RemoteException { ... } }

BImpl 的实例可以像您期望的那样作为 B 远程传递。因此,如果您想拥有适当的远程对象,您似乎需要在 Remote 之外实现一个独特的远程接口(interface)。

关于带有远程参数的 Java RMI 调用失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7472338/

相关文章:

java - Hibernate 无法从资源 : Employee. hbm.xml 读取映射

java - 如何使用 Java RMI 创建多个服务器?

Java RMI 引用

java - 在 OpenShift RedHat 服务器中配置 hibernate.cfg.xml

java - 有没有办法根据 Java 中的用户输入创建新变量

java - 使用 Java RegEx 如何仅返回完全匹配的内容?

java - 如何动态创建具有指定属性的 TextView?

java - 使用 Java 获取 JMeter 远程测试结果

java - 为什么服务器程序不退出?

java - 干净地关闭 rmi 服务器