使用远程参数的Java RMI调用失败

时间:2011-09-19 14:14:25

标签: java rmi

我从RMI注册表获取远程引用;我们称之为s。现在,s属于(接口)类型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是原生实施的,无法检查。所以,我完全失去了。显然,类型匹配,否则原始代码不应该编译,对吧?

这可能是什么原因?

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

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

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

1 个答案:

答案 0 :(得分:3)

原来我第二次编辑中提供的信息至关重要。

您只能导出/使用显式实现扩展Remote的接口的类的远程对象实例。特别是, 足以让一个类扩展UnicastRemoteObject ---即使那个实现了Remote!在这种情况下,一切编译和导出都很好,但实际上远程传递对象会导致上述异常。

我认为为没有远程接口的远程类型创建骨架/存根会以某种方式失败。应该有一个更好的治疗,但很好。

修改:澄清: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之外的区分远程接口。