Зачем Simple RMI Server нужна кодовая база?

1

ОС: Windows 7
JDK: 1.8.0_05

Я работаю над некоторыми простыми учебниками RMI, включая образец "Compute" Oracle (вычислить). Запуск моего сервера не требует кодовой базы, и ответы на вопросы, подобные этому, говорят, что "кодовая база не является обязательной". Тем не менее мой сервер не может зарегистрировать удаленный объект, если его интерфейс не находится в некоторой базе кода.

Я уверен, что мой интерфейс Compute доступен веб-серверу, запущенному на localhost, запустите сервер реестра следующим образом:

set CLASSPATH=
rmiregistry -J-Djava.rmi.server.codebase="http://localhost:80/"

И все работает нормально:

Exporting stub
Locating registry 
Binding stub
ComputeEngine bound

Но если я удалю Compute.class с пути веб-сервера, я получаю ClassNotFoundException:

Exporting stub
Locating registry 
Binding stub
java.rmi.ServerException: RemoteException occurred ...: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: edu.uweo.java2.rmi.compute.server.Compute

Из журнала веб-сервера я вижу, что была сделана попытка загрузить Compute.class:

GET '/edu/uweo/java2/rmi/compute/server/Compute.class'

Я также попытался запустить сервер реестра без указания кодовой базы:

set CLASSPATH=
rmiregistry

Когда я делаю это так, никто не пытается связаться с моим веб-сервером (что меня не удивляет), но я все еще получаю ClassNotFoundException.

Мой код выходит из учебника Oracle с помощью нескольких дополнительных печатных диагностических программ:

try
{
    String          name        = "Compute";
    ComputeEngine   engine      = new ComputeEngine();
    System.out.println( "Exporting stub" );
    Compute         stub        = 
       (Compute)UnicastRemoteObject.exportObject( engine, 0 );
    System.out.println( "Locating registry " );
    Registry        registry    = LocateRegistry.getRegistry();
    System.out.println( "Binding stub" );
    registry.rebind( name, stub );
    System.out.println( "ComputeEngine bound" );
}

Может ли кто-нибудь сказать мне, что мне не хватает?

Благодарю.

Теги:
rmi

2 ответа

1

Вы правы, вам не нужно использовать функцию codebase. Однако это означает, что ваш удаленный интерфейс, классы, от которого он зависит, и заглушка, если вы используете его, должны быть доступны как клиенту, так и реестру в их классах. Исключение, которое вы получаете, указывает на то, что в реестре эти классы отсутствуют на CLASSPATH.

  • 0
    Согласно документации, UnicastRemoteObject.exportObject () создает заглушку, а реестр просто связывает ее с именем. Зачем реестру декларация интерфейса?
  • 0
    Потому что доступ к нему осуществляется через сам RMI.
Показать ещё 2 комментария
0

Причина, по которой он работает, заключается в том, что Registry RMI реализован сам с помощью RMI. Поэтому, когда вы вызываете bind в одном приложении, фактическая реализация Registry в процессе rmiregistry получит объект-заглушку, реализующий все ваши Remote интерфейсы, так же как и все вызовы RMI, передающие ссылки на удаленные объекты.

Поэтому для процесса rmiregistry необходим доступ ко всем удаленным интерфейсам, реализованным объектом, который вы bind но, как вы уже обнаружили, его фактическое содержимое не имеет значения, поскольку реестр никогда не будет ссылаться на какие-либо методы на нем. Все, что он делает, - это передача удаленной заглушки вызывающим абонентам lookup и в этом случае заглушка сериализуется и передается в JVM удаленных абонентов, где создается эквивалентный заглушка, снова реализуя все удаленные интерфейсы, заглушка (и, следовательно, исходный объект) имеет реализованы.

Таким образом, все, что происходит с интерфейсами в процессе rmiregistry (если вы запустили его как отдельный процесс), заключается в том, что информация о удаленных интерфейсах, реализованных удаленным объектом, записывается, позволяя заглушке реализовать их соответствующим образом и передаваться всем другие удаленные приложения, выполняющие поиск.

В принципе, можно было бы реализовать весь реестр по-другому, не используя RMI и записывая реализованный интерфейс без необходимости в их файлах классов, однако это было бы огромным усилием, так как вам пришлось бы реализовать все, что вы получаете бесплатно когда просто используется RMI.

Но учтите, что если у вас есть только один сервер, вы можете упростить все, разрешив самому серверу создать реестр в своей собственной JVM. Тогда вам не нужно начинать другой процесс и не думать о его classpath/codebase.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню