Сбой вызова Java RMI с удаленными параметрами - PullRequest
1 голос
/ 19 сентября 2011

Я получаю удаленную ссылку из реестра RMI;давайте назовем это s.Теперь s имеет (интерфейсный) тип S, который предлагает метод m(A, B, int).

. На клиенте у меня есть реализации A и B, которые оба расширяют UnicastRemoteObject (и поэтому автоматически экспортируются).Рассмотрим случаи a и b соответственно.

Теперь я звоню 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.

Edit 2: Я реализовал несколько фиктивных методов на S для тестирования отдельных параметров.Оказывается, s.n(), s.t0(b) и s.t1(0) работают как положено;только s.t2(a) терпит неудачу.Это означает, что что-то не так с тем, как я реализовал A, не так ли?

Единственное различие между A и B (кроме реального контента, конечно) заключается в том, что A является классом, расширяющим UnicastRemoteObject и следует соглашению об удаленном интерфейсе, но не реализует выделенный удаленный интерфейс.B - это удаленный интерфейс, реализацию которого я передаю.

1 Ответ

3 голосов
/ 20 сентября 2011

Оказывается, информация, представленная в моем втором редактировании, имеет решающее значение.

Вы можете экспортировать / использовать в качестве удаленных объектов только экземпляры классов, которые явно реализуют интерфейс, расширяющий 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, если вы хотите иметь правильные удаленные объекты.

...