Ошибка при работе сервера RMI вне среды NetBeans
От: jsmet Россия  
Дата: 03.10.11 10:01
Оценка:
Добрый день, коллеги.
Попробовал создать простенькое программное обеспечение для обучения работе с RMI, и наткнулся на проблему ошибки java.io.EOFException, выдаваемой серверной или клиентской частью, если они запущены не из под NetBeans а с помощью ключей java. То есть, например, созданный архив .jar при запуске отдельно от среды (java -jar) выдает эту ошибку при считывании информации с экспортированного объекта RMI, а под средой все прекрасно, как написано в руководстве и на сайте Oracle в примерах. Перерыл весь интернет, даже переведенный с китайского статьи читал, везде эту ошибку знают, но ни одного стоящего решения не предлагается. Сразу: указание classpath в любом месте пробовал, не помогает, ключи java -D... известные мне тоже ситуацию не исправили. Внесение системной переменной CLASSPATH тоже оказалось бесполезным. Может, кто знает, как правильно указать ключи какие-нибудь при компилляции или запуске, или прописать что-то куда-то, чтобы заработало? Думал бы, что это системный баг RMI в java, но в NetBeans это ведь работает! Еще: никакого отношения не имеет к ошибке ClassNotFound создаваемого с помощью rmic файла _Stub, в этом я разобрался, просто похоже внешне.
Участок кода моей программы с серверной ее частью, куда от удивления вставил блок самопроверки со считыванием выгруженных данных, после чего в NetBeans все работает, отдельно, как ни запускай — ошибка:

//............................

//задание имени удаленного объекта
String serverObjectName = "WeatherService";

//порт по умолчанию для RMI
final int remotePort = 1099;
final String remoteHost = "localhost";


//запуск реестра rmiregistry со стандартным значением порта 1099
Registry registry = LocateRegistry.createRegistry(remotePort);

//Экспорт удаленного объекта
WeatherService remoteObject = (WeatherService)
UnicastRemoteObject.exportObject(service, 0);

String ip = InetAddress.getLocalHost().getHostAddress();
String localhost = InetAddress.getByName(remoteHost).
getHostAddress();

//регистрация удаленного объекта WeatherService в реестре
//rmiregistry
//Registry registry = LocateRegistry.getRegistry(remoteHost);
registry.rebind(serverObjectName, remoteObject);

service.addTextWeatherString("Текущий IP: " + ip);
service.addTextWeatherString("Localhost IP: " + localhost);
service.addTextWeatherString("Текущая погода:");

//контрольный вывод полученного содержимого о погоде
java.util.List<WeatherBean> list =
service.getWeatherInformation();
for (int i = 0; i < list.size(); i++) {

WeatherBean wb = list.get(i);
service.addTextWeatherString(wb.getCityName() + " " +
wb.getDescription() + " " + wb.getTemperature());
}

//проверка корректности экспорта удаленного объекта
//registry = LocateRegistry.getRegistry();

String[] regArr = registry.list();

java.util.List<String> regList = Arrays.asList(regArr);

if (regList.contains(serverObjectName)) {

//поиск удаленного объекта WeatherService
Remote remote = registry.lookup(serverObjectName);

/*
//работает, даже если убрать этот комментарий и
//использовать прямое преобразование вместо Proxy
WeatherService weatherService = (WeatherService)
registry.lookup(serverObjectName);
*/

if (Proxy.isProxyClass(remote.getClass())) {

//получение proxy вместо прямого преобразования
Proxy proxy = (Proxy) remote;

//тут надо еще и вызвать специальный указатель
InvocationHandler invocationHandler =
Proxy.getInvocationHandler(proxy);


//преобразование к виду Remote из Proxy в связи с
//изменениями в v.6
WeatherService weatherService = (WeatherService)
Proxy.newProxyInstance(
WeatherService.class.getClassLoader(),
new Class[] { WeatherService.class },
invocationHandler);

//прверка содержимого созданного удаленного объекта
service.addTextWeatherString(
"Проверка содержимого удаленного объекта " +
"WeatherService:");

service.showEvent("Получение удаленной информации");
list = weatherService.getWeatherInformation();

service.showEvent("Вывод содержимого удаленного объекта");
for (int i = 0; i < list.size(); i++) {

WeatherBean wb = list.get(i);
service.addTextWeatherString(wb.getCityName() + " " +
wb.getDescription() + " " + wb.getTemperature());
}
}
}

service.showEvent("WeatherService успешно запущен");

//............................

Текст ошибки, выдаваемой вне среды NetBeans, выглядит следующим образом:

java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.io.EOFException
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:173)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy0.getWeatherInformation(Unknown Source)
at deitel.rmi.weather.server.WeatherServiceImpl.main(WeatherServiceImpl.java:308)
Caused by: java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:375)
at java.io.ObjectInputStream$BlockDataInputStream.readInt(ObjectInputStream.java:2775)
at java.io.ObjectInputStream.readInt(ObjectInputStream.java:949)
at javax.swing.ImageIcon.readObject(ImageIcon.java:441)
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 java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at java.util.ArrayList.readObject(ArrayList.java:593)
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 java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)
... 4 more

Заранее спасибо за любой разумный ответ.
rmi java java.io.eofexception
Re: Ошибка при работе сервера RMI вне среды NetBeans
От: Blazkowicz Россия  
Дата: 03.10.11 15:14
Оценка:
Здравствуйте, jsmet, Вы писали:

RMI registry запущен?
http://download.oracle.com/javase/tutorial/rmi/running.html
Re[2]: Ошибка при работе сервера RMI вне среды NetBeans
От: Аноним  
Дата: 04.10.11 05:04
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, jsmet, Вы писали:


B>RMI registry запущен?

B>http://download.oracle.com/javase/tutorial/rmi/running.html

Увы. Разными способами. И отдельно, как программу. Кстати, так, как описано на сайте, то есть "start rmiregistry" — не работает, работает просто если rmiregistry. Разбираться с этим фактом не стал — и так проблем с этим немеряно. В теле самой программы это делается командой LocateRegistry.createRegistry() — результат такой же, как и запускать отдельно. Причем в среде NetBeans проходит и так, и так и вот так. Отдельно запускаешь — хоть упаковывай в jar, хоть из классов — ни за что. Что NetBeans внутри себя делает при компилляции и запуске, что все получается — для меня полная загадка. Наверное, корректо указывает все возможные комбинации опций -D.... Пробовал бороться с этим -classpath — никакого эффекта, хоть как варьируй. Даже пытался запускать rmiregistry -J-D-classpath=..., толку столько же. Переменную среды CLASSPATH хоть стирай, хоть наполняй — результат опять не меняется. Стал копаться в Инете — вопросов таких сотни, с этой ошибкой, ответов с решениями ноль. Советы те-же — ответы на них — не помогает. У меня то же самое. Сейчас попытаюсь побороться с этими RMISecurityManager() и дурацкими файлами политик, но что-то надежды мало. По моему, это только запреты, а в NetBeans, да и в примерах на сайте Oracle все работает без этих политик, и ничего, но не понятно, почему. Странная проблема в целом, отнес бы к глюкам, там с версии 6 и выше поменялся кардинально способ работы c RMI, старый дает другую ошибку — не находит класс _Stub, хотя он лежит себе рядом в том же каталоге. Как я понял, там его запрещает "увидеть" какой-то системный булевский параметр, но пытался его сбросить через указанный на сайте пакет — не нашел, где он там. Ну свинство полное. Думал, угробили этот RMI навсегда и фиг с ним, но в среде заработало — сидел и недоумевал. Надо же так все усложнить "улучшением"!
Re: Ошибка при работе сервера RMI вне среды NetBeans
От: tavr  
Дата: 04.10.11 05:43
Оценка:
Здравствуйте, jsmet, Вы писали:

Похоже на ошибку десериализации. Что за лист ImageIcon вы там пересылаете?

J>Текст ошибки, выдаваемой вне среды NetBeans, выглядит следующим образом:

J>java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
J> java.io.EOFException
J> at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:173)
J> at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
J> at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
J> at $Proxy0.getWeatherInformation(Unknown Source)
J> at deitel.rmi.weather.server.WeatherServiceImpl.main(WeatherServiceImpl.java:308)
J>Caused by: java.io.EOFException
J> at java.io.DataInputStream.readInt(DataInputStream.java:375)
J> at java.io.ObjectInputStream$BlockDataInputStream.readInt(ObjectInputStream.java:2775)
J> at java.io.ObjectInputStream.readInt(ObjectInputStream.java:949)
J> at javax.swing.ImageIcon.readObject(ImageIcon.java:441)
J> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
J> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
J> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
J> at java.lang.reflect.Method.invoke(Method.java:597)
J> at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
J> at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
J> at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
J> at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
J> at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
J> at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
J> at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
J> at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
J> at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
J> at java.util.ArrayList.readObject(ArrayList.java:593)
J> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
J> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
J> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
J> at java.lang.reflect.Method.invoke(Method.java:597)
J> at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
J> at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
J> at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
J> at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
J> at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
J> at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
J> at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)
J> ... 4 more

J>Заранее спасибо за любой разумный ответ.
Re[2]: Ошибка при работе сервера RMI вне среды NetBeans
От: Аноним  
Дата: 04.10.11 06:17
Оценка:
Здравствуйте, tavr, Вы писали:

T>Здравствуйте, jsmet, Вы писали:


T>Похоже на ошибку десериализации. Что за лист ImageIcon вы там пересылаете?


Похоже, еще как похоже. Взял пример из книги и тупо вставил. Там передается через интерфейс

import java.io.*;
import java.rmi.*;
import java.util.*;

public interface WeatherService extends Remote, Serializable {
//получение вектора объектов WeatherBean от сервера
public List getWeatherInformation() throws RemoteException;

}

Состояние погоды в городах. При преобразовании к Remote полчается объект вида

import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;

public class WeatherBean implements Serializable {

//название города
private String cityName;
//температура в городе
private String temperature;
//описание погоды
private String description;
//изображение характера погоды
private ImageIcon image;

private static Properties imageNames;

//инициализация объекта imageNames при загрузке класса WeatherInfo в
//память
static {
//создание таблицы свойств
imageNames = new Properties();

//загрузка описаний погоды и имен изображений из файла свойств
try {
//загрузка содержимого файла свойств
imageNames.load(new FileInputStream("imagenames.properties"));

//обработка исключений при открытии файла
} catch (IOException ioException) {
ioException.printStackTrace();
}
//конец блока static
}

//конструктор WeatherBean
public WeatherBean(String city, String weatherDescription, String
cityTemperature) {
cityName = city;
temperature = cityTemperature;
description = weatherDescription.trim();

//получение имени изображения или использование имени noinfo.jpg,
//если описание погоды не найдено
image = new ImageIcon("images/" +
imageNames.getProperty(description, "noinfo.gif"));
}

//получение названия города
public String getCityName() {
return cityName;
}

//получение температуры
public String getTemperature() {
return temperature;
}

//получение описания погоды
public String getDescription() {
return description;
}

//получение изображения характера погоды
public ImageIcon getImage() {
return image;
}

}

Потом из него функциями извлекается название города, описатель погоды (Ясно, дождь), записанный в файле свойств и соответствующая ему иконка погоды ImageIcon. В NetBeans (если запустить параллельно и сервер и клиент) все это прелестно доезжает до клиента. Из командной строки — труп. То есть даже свое собственное, засунутое в RMI без ошибок, этот "сервер" считать нормально не может. Нашел в jdk еще и java-rmi.exe, добавил по максимуму в ключи -D всякие java.rmi.server.codebase и java.rmi.security.policy, создал файл policy по образцу, но дебилу все равно плохо: при запуске ни на что не ругается, но результат опять плачевный. Осталось стойкое ощущение, что там в sun знают, как правильно это запускать, но им лень описать это в инструкциях. Для NetBeans они это просто вложили, а так — долбайтесь сами, как хотите. Сайту Oracle тем более пофигу — там все правильно написано, раз-два, и все просто, на деле оно так в клиенте работать не хочет, не преобразуется в Remote по новому алгоритму начиная с v6, надо в Proxy, потом в invocationHandler, потом только в Remote, и только тогда в интерфейсный объект. Иначе ошибка преобразования класса. Грозное "ахтунг, минен!" на эту тему там есть в технотах где-то, но опять же, в основном хелпе об этом ни слова. Делайте так, как написано, и все у вас получится! На деле сотни недоуменных вопросов: как это? И no ideas в ответ. При этом опять же, NetBeans сам умеет это объехать, а из командной строки — одни ошибки. Чего-то явно мы просто не знаем, чего в этих ключах писать, и все.
Re: Ошибка при работе сервера RMI вне среды NetBeans
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 04.10.11 07:22
Оценка:
Здравствуйте, jsmet, Вы писали:

J>Добрый день, коллеги.

J>Попробовал создать простенькое программное обеспечение для обучения работе с RMI, и наткнулся на проблему ошибки java.io.EOFException, выдаваемой серверной или клиентской частью, если они запущены не из под NetBeans а с помощью ключей java. То есть, например, созданный архив .jar при запуске отдельно от среды (java -jar) выдает эту ошибку при считывании информации с экспортированного объекта RMI, а под средой все прекрасно, как написано в руководстве и на сайте Oracle в примерах. Перерыл весь интернет, даже переведенный с китайского статьи читал, везде эту ошибку знают, но ни одного стоящего решения не предлагается. Сразу: указание classpath в любом месте пробовал, не помогает, ключи java -D... известные мне тоже ситуацию не исправили. Внесение системной переменной CLASSPATH тоже оказалось бесполезным. Может, кто знает, как правильно указать ключи какие-нибудь при компилляции или запуске, или прописать что-то куда-то, чтобы заработало? Думал бы, что это системный баг RMI в java, но в NetBeans это ведь работает! Еще: никакого отношения не имеет к ошибке ClassNotFound создаваемого с помощью rmic файла _Stub, в этом я разобрался, просто похоже внешне.
J>Участок кода моей программы с серверной ее частью, куда от удивления вставил блок самопроверки со считыванием выгруженных данных, после чего в NetBeans все работает, отдельно, как ни запускай — ошибка:

J>Заранее спасибо за любой разумный ответ.

Какая версия джавы из командной строки запускается? Та же, что в Netbeans?
El pueblo unido jamás será vencido.
Re[2]: Ошибка при работе сервера RMI вне среды NetBeans
От: jsmet Россия  
Дата: 04.10.11 07:42
Оценка:
Здравствуйте, bl-blx, Вы писали:

BB>Здравствуйте, jsmet, Вы писали:


J>>Добрый день, коллеги.

J>>Попробовал создать простенькое программное обеспечение для обучения работе с RMI, и наткнулся на проблему ошибки java.io.EOFException, выдаваемой серверной или клиентской частью, если они запущены не из под NetBeans а с помощью ключей java. То есть, например, созданный архив .jar при запуске отдельно от среды (java -jar) выдает эту ошибку при считывании информации с экспортированного объекта RMI, а под средой все прекрасно, как написано в руководстве и на сайте Oracle в примерах. Перерыл весь интернет, даже переведенный с китайского статьи читал, везде эту ошибку знают, но ни одного стоящего решения не предлагается. Сразу: указание classpath в любом месте пробовал, не помогает, ключи java -D... известные мне тоже ситуацию не исправили. Внесение системной переменной CLASSPATH тоже оказалось бесполезным. Может, кто знает, как правильно указать ключи какие-нибудь при компилляции или запуске, или прописать что-то куда-то, чтобы заработало? Думал бы, что это системный баг RMI в java, но в NetBeans это ведь работает! Еще: никакого отношения не имеет к ошибке ClassNotFound создаваемого с помощью rmic файла _Stub, в этом я разобрался, просто похоже внешне.
J>>Участок кода моей программы с серверной ее частью, куда от удивления вставил блок самопроверки со считыванием выгруженных данных, после чего в NetBeans все работает, отдельно, как ни запускай — ошибка:

J>>Заранее спасибо за любой разумный ответ.

BB>Какая версия джавы из командной строки запускается? Та же, что в Netbeans?

Да абсолютно та же, из того-же каталога, только в закладке "Сервис"-"Платформы" NetBeans перечислены библиотеки, а не ехе-файлы (скриншот прилагаю). Он из библиотек что-ли компиллятор сам делает, поэтому у него всегда все работает, а мы как идиоты javaю.exe -classpath... и т.п.?
Re[3]: Ошибка при работе сервера RMI вне среды NetBeans
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 04.10.11 08:43
Оценка:
Здравствуйте, jsmet, Вы писали:

J>Здравствуйте, bl-blx, Вы писали:


BB>>Здравствуйте, jsmet, Вы писали:


J>>>Добрый день, коллеги.

J>>>Попробовал создать простенькое программное обеспечение для обучения работе с RMI, и наткнулся на проблему ошибки java.io.EOFException, выдаваемой серверной или клиентской частью, если они запущены не из под NetBeans а с помощью ключей java. То есть, например, созданный архив .jar при запуске отдельно от среды (java -jar) выдает эту ошибку при считывании информации с экспортированного объекта RMI, а под средой все прекрасно, как написано в руководстве и на сайте Oracle в примерах. Перерыл весь интернет, даже переведенный с китайского статьи читал, везде эту ошибку знают, но ни одного стоящего решения не предлагается. Сразу: указание classpath в любом месте пробовал, не помогает, ключи java -D... известные мне тоже ситуацию не исправили. Внесение системной переменной CLASSPATH тоже оказалось бесполезным. Может, кто знает, как правильно указать ключи какие-нибудь при компилляции или запуске, или прописать что-то куда-то, чтобы заработало? Думал бы, что это системный баг RMI в java, но в NetBeans это ведь работает! Еще: никакого отношения не имеет к ошибке ClassNotFound создаваемого с помощью rmic файла _Stub, в этом я разобрался, просто похоже внешне.
J>>>Участок кода моей программы с серверной ее частью, куда от удивления вставил блок самопроверки со считыванием выгруженных данных, после чего в NetBeans все работает, отдельно, как ни запускай — ошибка:

J>>>Заранее спасибо за любой разумный ответ.

BB>>Какая версия джавы из командной строки запускается? Та же, что в Netbeans?

J>Да абсолютно та же, из того-же каталога, только в закладке "Сервис"-"Платформы" NetBeans перечислены библиотеки, а не ехе-файлы (скриншот прилагаю). Он из библиотек что-ли компиллятор сам делает, поэтому у него всегда все работает, а мы как идиоты javaю.exe -classpath... и т.п.?


А ОС какая? Параметр -Djava.awt.headless=true — не помогает?
El pueblo unido jamás será vencido.
Re: Ошибка при работе сервера RMI вне среды NetBeans
От: Аноним  
Дата: 04.10.11 09:07
Оценка:
Попробуй что то попроще —
вот это http://download.oracle.com/javase/tutorial/rmi/server.html например, и посмотри работает у тя оно или нет..
Если таки заработает, тогда попробуй посмотреть что принципиально отличается от твоего примера...А дальше уже будем смотреть, может выложишь свою прогу куда то и кто то скачает попробует локально запустить...


J>Добрый день, коллеги.

J>Попробовал создать простенькое программное обеспечение для обучения работе с RMI
Re[3]: Ошибка при работе сервера RMI вне среды NetBeans
От: tavr  
Дата: 05.10.11 05:50
Оценка:
Здравствуйте, Аноним, Вы писали:

T>>Похоже на ошибку десериализации. Что за лист ImageIcon вы там пересылаете?

А>Похоже, еще как похоже. Взял пример из книги и тупо вставил. Там передается через интерфейс
из первого что приходит в голову — вне Netbeans недоступны ресурсы, в частности папка images
попробуйте вообще убрать image (заодно и imageNames) из полей класса, привести класс его к "нормальному" виду: дефолтный конструктор, геттеры/сеттеры
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.