Как мне установить classpath, который использует rmiregistry?
Я пытаюсь сделать приложение клиент / сервер Java RMI. Я сталкиваюсь с проблемами при запуске серверной части моего приложения, так как оно продолжает работать в ClassNotFoundException во время вызова метода Registry.bind(), когда я пытаюсь запустить серверную часть приложения.
Я начал с простого урока здесь: http://docs.oracle.com/javase/1.5.0/docs/guide/rmi/hello/hello-world.html. После выполнения этих инструкций он изначально выдавал исключение ClassNotFoundException с жалобой на то, что не может найти "example.hello.Hello". Я смог решить эту проблему, запустив rmiregistry FROM из каталога destDir в учебном пособии, поскольку rmiregistry, по-видимому, использует свой начальный начальный каталог как часть своего пути к классам.
После этого я запустил другое тестовое приложение, и все было в порядке, пока я не начал использовать сторонние jar-файлы в своем классе серверов. Теперь Registry.bind() генерирует исключение ClassNotFoundException, если мой класс сервера ссылается на что-либо в любом jar-файле, так как приложение rmiregistry не знает об этих jar-файлах.
Насколько я могу судить, rmiregistry не принимает никаких аргументов запуска пути к классам, поэтому мне интересно, как я могу сказать, какой путь к классу я хочу, чтобы он подтвердил. В соответствии с руководством здесь: http://docs.oracle.com/javase/tutorial/rmi/running.html"вы должны убедиться, что в оболочке или окне, в котором вы будете запускать rmiregistry, не задана переменная среды CLASSPATH или имеет переменную среды CLASSPATH, которая не включает путь к каким-либо классам, которые вы хотите загрузить для клиентов ваших удаленных объектов." Это звучит как противоположность того, что мне нужно... или я читаю это неправильно? У кого-нибудь был какой-либо успех при запуске клиента / сервера RMI, который использует сторонние jar (commons-io, commons-logging и rmiio, в моем случае)?
Это на Windows, между прочим.
Обновление я нашел способ обойти это. Смотрите мой ответ ниже.
4 ответа
(Первоначально я опубликовал этот ответ в качестве обновления своего вопроса. В соответствии с предложением Зекаса в одном из комментариев я перенесу его в раздел ответов.)
Я смог запустить серверную часть, не повинуясь предложению во втором уроке, указанном в моем вопросе выше:
"Вы должны убедиться, что оболочка или окно, в котором вы будете запускать rmiregistry, либо не имеют установленной переменной среды CLASSPATH, либо имеют переменную среды CLASSPATH, которая не включает путь к каким-либо классам, которые вы хотите загрузить на клиенты ваших удаленных объектов".
Я создал переменную среды CLASSPATH и добавил к ней свой выходной каталог.class и каждый из сторонних jar-файлов. Я думал, что пытался сделать это раньше, но, думаю, нет... Просто думал, что оставлю свое решение на случай, если у кого-то еще возникнет такая же проблема.
Замечания об отмене сброса CLASSPATH применимы только в том случае, если вы используете функцию кодовой базы RMI, что подразумевается под загадочным замечанием о загрузке классов.
Если вы не используете функцию кодовой базы, просто либо:
- Установите переменную среды CLASSPATH, как требуется, перед запуском
rmiregistry,
как показано в другом месте здесь, или - Начните
rmiregistry
с-J-Djava.class.path=...
- Запустите Реестр внутри вашего сервера JVM, с
LocateRegistry.createRegistry().
Во многих отношениях это лучшее решение, поскольку оно живет и умирает вместе с JVM, разделяет его путь к классу и, кстати, также соответствует требованиям для функции кодовой базы.
Если вы выполняете (3), вы должны сохранить возвращаемое значение в статической переменной, чтобы предотвратить его сборку мусора, что приводит к тому, что реестр не экспортируется, что может привести к DGC удаленного объекта, что может привести к его GC'd, который приведет к выходу прослушивающего потока, что может привести к выходу всей JVM.
Не существует специфичного для RMI реестра пути к классу Java. Он должен использовать тот же путь к классам, что и остальная часть системы Java. Вы можете установить ваш classpath, указав его в командной строке или в вашей операционной системе. Хотя этот документ немного устарел, он должен указать вам правильное направление.
Пример того, как установить classpath для rmiregistry
Win32:
set CLASSPATH=c:\home\ann\src;c:\home\ann\public_html\classes\compute.jar
UNIX:
setenv CLASSPATH /home/ann/src:/home/ann/public_html/classes/compute.jar