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 очков репутации.

Другие вопросы по тегам