Java RMI call with remote parameters fails
I obtain a remote reference from an RMI registry; lets call it s
. Now, s
is of (interface) type S
which offers a method m(A, B, int)
.
On the client, I have implementations of A
and B
which both extend UnicastRemoteObject
(and are therefore automatically exported). Consider instances a
and b
, respectively.
Now I call m(a, b, 0)
. It compiles, but fails at runtime with the very non-informative
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 s开发者_Python百科un.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]
Sadly, NativeMethodAccessorImpl.invoke0
is natively implemented and can not be inspected. So, I am at a total loss. Obviously, types match, otherwise the original code should not compile, right?
What can be reasons for this?
Edit: We use Java 6. The error can be reproduced on Ubuntu 11.04 32bit, Ubuntu 10.10 64bit and Windows 7 32bit.
Edit 2: I implemented some dummy methods on S to test individual parameters. Turns out, s.n()
, s.t0(b)
and s.t1(0)
work as expected; only s.t2(a)
fails. This implies that something is wrong with how I implemented A
, doesn't it?
The only striking difference between A
and B
(aside from actual content, of course) is that A
is a class extending UnicastRemoteObject
and follows the convention of a remote interface but does not implement a distinguished remote interface. B
is a remote interface an implementation of which I pass.
Turns out the information provided in my second edit is crucial.
You can only export/use as remote objects instances of classes that explicitly implement an interface which extends Remote
. It is, in particular, not sufficient to have a class extending UnicastRemoteObject
---even though that one implements Remote
! In that case, everything compiles and exports just fine, but actually passing the object remotely causes the above exception.
I suppose that creating skeletons/stubs for a remote type for which no remote interface exists somehow fails. There should be a better treatment for that, but well.
Edit: To clarify: UnicastRemoteObject
implements Remote
. Now, having something like
class A extends UnicastRemoteObject { void m() throws RemoteException {} }
is not sufficient, even though A
implements Remote
indirectly. You will be able to instantiate (i.e. export), but not pass it remotely as an A
.
You need to do
interface B extends Remote { void n() throws RemoteException; }
class BImpl extends UnicastRemoteObject implements B { void n() throws RemoteException { ... } }
Instances of BImpl
can be passed remotely as B
as you would expect. So it appears that you need to implement a distinguished remote interface aside from Remote
if you want to have proper remote objects.
精彩评论