Java RMI codebase не работает
Насколько я понимаю, кодовая база для RMI, которую я установил на клиенте, будет передана на сервер. Затем сервер использует эту кодовую базу для поиска классов, которых нет в пути к классам серверов.
Пока все необходимые классы доступны в пути к классам серверов, удаленный вызов метода работает просто отлично. Затем я попытался удалить требуемый класс из пути к классам серверов и вместо этого указал новое местоположение для требуемого класса в свойстве codebase при запуске клиента RMI. К сожалению это даст мне ClassNotFoundException: java.lang.ClassNotFoundException: client.Pi
Трассировки стека:
java.rmi.ServerException: RemoteException occurred in server thread; nested exce
ption is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested excep
tion is:
java.lang.ClassNotFoundException: client.Pi
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Sou
rce)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Sour
ce)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknow
n Source)
at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
at sun.rmi.server.UnicastRef.invoke(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unkn
own Source)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
at com.sun.proxy.$Proxy0.executeTask(Unknown Source)
at client.ComputePi.main(ComputePi.java:26)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested ex
ception is:
java.lang.ClassNotFoundException: client.Pi
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Sou
rce)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Sour
ce)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: client.Pi
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.rmi.server.LoaderHandler$Loader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClassForName(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClass(Unknown Source)
at sun.rmi.server.LoaderHandler.loadClass(Unknown Source)
at java.rmi.server.RMIClassLoader$2.loadClass(Unknown Source)
at java.rmi.server.RMIClassLoader.loadClass(Unknown Source)
at sun.rmi.server.MarshalInputStream.resolveClass(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at sun.rmi.server.UnicastRef.unmarshalValue(Unknown Source)
... 11 more
Запуск сервера:
C:\TEMP\RMI\RMIDemo\src>java
-cp C:\Users\samue_000\public_html\classes\compute.jar;C:\TEMP\RMI\RMIDemo\src
-Djava.security.policy=server.policy
-Djava.rmi.server.useCodebaseOnly=false
engine.ComputeEngine
>> ComputeEngine bound
Запуск клиента:
C:\TEMP\RMI\RMIDemo\src>java
-cp C:\Users\samue_000\public_html\classes\compute.jar;c:\Temp\RMI\RMIDemo\src;c:\temp
-Djava.security.policy=client.policy
-Djava.rmi.server.codebase=file:/C:/Users/samue_000/public_html/classes
client.ComputePi
Внутри classpath клиента (c:\temp) находится требуемый класс client.Pi, который также требуется клиенту. Чтобы сообщить серверу, где находится этот класс, я поместил копию в отдельную папку и указал эту папку свойством codebase. Точное местоположение этого класса - C:/Users/samue_000/public_html/classes/client/Pi.class. Все работает на одной физической машине (без виртуальной машины). Поэтому я не понимаю, почему сервер не получает кодовую базу от клиента и загружает необходимый класс client.Pi.
Я старался свести размещенную информацию к необходимой части, чтобы не переполнять этот пост. Если требуется дополнительная информация, чтобы помочь мне решить эту проблему, пожалуйста, дайте мне знать. Это сводит меня с ума. Я работаю над этим вопросом часами и днями...
Изменить: я использовал почти тот же код, как описано в этой статье от оракула. Единственное отличие состоит в том, что я создаю реестр rmi программно, а не запускаю отдельный реестр. Так что не должно быть ничего плохого в самом коде. Пока класс Pi находится в classpath сервера, он работает просто отлично. Но как только класс Pi существует только внутри кодовой базы и пути к классу Клиента, он больше не будет работать.
1 ответ
Обычно URL-адреса кодовой базы RMI являются URL-адресами HTTP и обычно ссылаются на файл JAR, а не на каталог.
-Djava.rmi.server.codebase=file:/C:/Users/samue_000/pubic_html/classes
Это file:
URL, и он будет работать только в той системе, к которой он относится. Если сервер находится на другом хосте, он не станет ни головой, ни хвостом.
Однако, поскольку это все на той же машине, это должно работать. Вы можете разместить удаленный интерфейс?
Не пропускайте / в конце и попробуйте:
-Djava.rmi.server.codebase=file:/C:/Users/samue_000/public_html/classes/
Вы можете загрузить файлы классов. Но вам нужно закончить путь разделителем пути. это то, что говорится в документации. Это должен был быть комментарий, но я потерял право комментировать этот сайт, пока не наберу 50 очков репутации.