передача класса по сети (изза проблем со Swing передаю форму как файл класса [прямого наследника класса, который есть на сервере и клиенте]). Когда запускаешь программу-клиент просто как jar-файл, всё работает (класс передаётся, загружается из сырой памяти и внедряется (создаётся экземпляр объекта этого класса).
Когда запускаешь клиента через Java Web Start, при вызове "собирателя класса" (метод defineClass), он выбрасывает ClassCircularityError и в качестве класса-причины указывается класс-предок (тот базовый класс, который есть на сервере и на клиенте).
while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
Скажи .net корпорации Microsoft! (c) ghostwolf 2004
7 раз поищи в стандартной библиотеке, 1 раз накодь своё.
Re: Java Web Start+передача класса по сети ClassCircularityE
Здравствуйте, Волк-Призрак, Вы писали:
ВП>передача класса по сети (изза проблем со Swing передаю форму как файл класса [прямого наследника класса, который есть на сервере и клиенте]). Когда запускаешь программу-клиент просто как jar-файл, всё работает (класс передаётся, загружается из сырой памяти и внедряется (создаётся экземпляр объекта этого класса). ВП>Когда запускаешь клиента через Java Web Start, при вызове "собирателя класса" (метод defineClass), он выбрасывает ClassCircularityError и в качестве класса-причины указывается класс-предок (тот базовый класс, который есть на сервере и на клиенте).
Можешь привести код, а то не совсем понятно, что там у тебя происходит. Вполне возможно, что класслоадер бросает исключение (в defineClass) потому, что класс уже был загружен.
--
Дмитро
Re[2]: Java Web Start+передача класса по сети ClassCirculari
Здравствуйте, dshe, Вы писали:
ВП>>передача класса по сети (изза проблем со Swing передаю форму как файл класса [прямого наследника класса, который есть на сервере и клиенте]). Когда запускаешь программу-клиент просто как jar-файл, всё работает (класс передаётся, загружается из сырой памяти и внедряется (создаётся экземпляр объекта этого класса). ВП>>Когда запускаешь клиента через Java Web Start, при вызове "собирателя класса" (метод defineClass), он выбрасывает ClassCircularityError и в качестве класса-причины указывается класс-предок (тот базовый класс, который есть на сервере и на клиенте).
D>Можешь привести код, а то не совсем понятно, что там у тебя происходит. Вполне возможно, что класслоадер бросает исключение (в defineClass) потому, что класс уже был загружен.
Огромное спасибо за напоминание о возможности "повтороной" загрузки того, что уже загружено или уже есть у клиента.
Вот исправленная версия класса BytesClassLoader:
/*
(c) 2004 Константин Николаевич Исаев aka Ghostwolf, Волк-Призрак. ghostwolf@inbox.ru
Если кому нужно - пользуйте на здоровье, хоть в коммерческих целях, хоть в личных. но
патентовать и иным способом присваивать права на эту и созданную на её основе
интеллектуальную собственость не разрешаю.
Данный исходный текст разрешаю к распространению в случае неизменности данной записи
об авторском праве и условиях распространения, и самого исходного текста.
*/public final class BytesClassLoader extends ClassLoader {
private byte[] bytes=null;
public Class findClass(String name) {
try
{
return getClass().forName(name);
}catch(Throwable err)
{}
Class c=defineClass(name,bytes,0,bytes.length);
resolveClass(c);
return c;
}
public BytesClassLoader(byte[] classfilebytes){
super();
bytes=classfilebytes;
}
}
А вот класс, который используется как часть "протокола" — "генератор" байтовых блоков с классами):
/*
(c) 2004 Константин Николаевич Исаев aka Ghostwolf, Волк-Призрак. ghostwolf@inbox.ru
Если кому нужно - пользуйте на здоровье, хоть в коммерческих целях, хоть в личных. но
патентовать и иным способом присваивать права на эту и созданную на её основе
интеллектуальную собственость не разрешаю.
Данный исходный текст разрешаю к распространению в случае неизменности данной записи
об авторском праве и условиях распространения, и самого исходного текста.*/import java.lang.*;
import java.io.*;
import java.net.*;
public final class SerializedClass implements Serializable {
private byte[] data=null;
public boolean isValid(){return (data!=null)&&(data.length>0);}
public SerializedClass(final Class theclass) throws NullPointerException,IOException
{
if (theclass==null) throw new NullPointerException("SerializedClass: Не выбран класс для сериализации");
ClassLoader cl=getClass().getClassLoader();
StringBuffer cn=new StringBuffer(theclass.getName());
for(int i=0;i<cn.length();i++){
if(cn.charAt(i)=='.'){cn.setCharAt(i,'/');}
}
String scn=cn.toString()+".class";
System.out.println("Searching for class "+scn);
URL clurl=cl.getResource(scn);
if(clurl==null)
clurl=cl.getSystemResource(scn);
if(clurl==null)
throw new NullPointerException("Нет возможности получить файл класса.");
URLConnection clurlconn=clurl.openConnection();
int len=clurlconn.getContentLength();
byte[] buffer=new byte[len];
InputStream clis=clurlconn.getInputStream();
int bytesreaden=clis.read(buffer);
System.out.println("From the url ["+clurl.toString()+"] readen "+new Integer(bytesreaden)+" of "+new Integer(buffer.length)+" declared bytes." );
if(bytesreaden!=buffer.length) throw new ClassFormatError("From the url ["+clurl.toString()+"] readen "+new Integer(bytesreaden)+" of "+new Integer(buffer.length)+" of declared bytes");
data=buffer;
buffer=null;
clis.close();
}
public Class loadClass() throws IllegalStateException {
if(!isValid()) throw new IllegalStateException("SerializedClass: Класс повреждён при транспортеровке");
return new BytesClassLoader(data).findClass(null);
}
}
Сериализованные классы сами по себе берутся, как ресурсы, из того jar-а, в котором они лежат.
Имя берётся из класса, который подан на сериализацию.
Сначала я писал так:
Class theclass=LoginForm.class;
ObjectOutputStream out=getConnectionOutput();
out.writeobject(theclass);
//и наоборот при получении - readObject итп.
Но так не получилось. вот и переделал в вариант с SerializedClass и BytesClassLoader.
while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
Скажи .net корпорации Microsoft! (c) ghostwolf 2004
7 раз поищи в стандартной библиотеке, 1 раз накодь своё.
Re[3]: Java Web Start+передача класса по сети ClassCirculari
Здравствуйте, Волк-Призрак, Вы писали:
ВП>Здравствуйте, dshe, Вы писали:
ВП>>>передача класса по сети (изза проблем со Swing передаю форму как файл класса [прямого наследника класса, который есть на сервере и клиенте]). Когда запускаешь программу-клиент просто как jar-файл, всё работает (класс передаётся, загружается из сырой памяти и внедряется (создаётся экземпляр объекта этого класса). ВП>>>Когда запускаешь клиента через Java Web Start, при вызове "собирателя класса" (метод defineClass), он выбрасывает ClassCircularityError и в качестве класса-причины указывается класс-предок (тот базовый класс, который есть на сервере и на клиенте).
Извини, но у меня сложилось впечатление, что ты занимаешься извратом. Вполне возможно, что для решения твоей основной задачи тебе не нужны хитрые мансы с класслоадерами. Если тебе нужно передать класс по сети, то почему бы его не запаковать в jar как и все остальные классы и скачать тем же Web Start'ом?
Опиши проблему со Swing'ом, из-за которой ты решил передавать классы по сети таким образом.
--
Дмитро
Re[4]: Java Web Start+передача класса по сети ClassCirculari
Здравствуйте, dshe, Вы писали:
D>Извини, но у меня сложилось впечатление, что ты занимаешься извратом. Вполне возможно, что для решения твоей основной задачи тебе не нужны хитрые мансы с класслоадерами. Если тебе нужно передать класс по сети, то почему бы его не запаковать в jar как и все остальные классы и скачать тем же Web Start'ом?
Дело в том, что я использую Java web start не в полной мере.
Де факто я использую jaws только для того, чтобы получить имя сервера, с которого бралась программа
(BasicService.getCodeBase().getHostName()).
Я хотел, чтобы классы брались из изменяемого во время работы программы источника.
Скажем из папки BOOM/Server/ActionClasses/*.class
где * имя формы для действия, берётся из БД,
Это сейчас имя класса берётся из самого класса. потом это изменю так,
чтобы он не сам класс принимал в конструкторе, а просто имя.
D>Опиши проблему со Swing'ом, из-за которой ты решил передавать классы по сети таким образом.
Сначала я передавал Swing-формы как есть, и принимая, проверял объекты на instanceof.
Но так как swing не приспособлен для long term persistence, согласно документации...
Это выглядело как ошибка при приёме объекта, про разные serial у класса javax.swing.JComponent. — т.е. JComponent в 1.3.1 (версиимя в которой компилирую и запускаю сервер) и в 1.4.2.06 (версия где запускается клиент).
Мне нужна защита от "разных версий свинга" у сервера и у клиента.
И динамизм нужен. Чтобы форму например логина можно было поменять. Или добавить новую — скажем расширенный поиск автомобилейв бд. Без остановки сервера. Копируешь класс формы — и регистрируешь её в бд.
while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
Скажи .net корпорации Microsoft! (c) ghostwolf 2004
7 раз поищи в стандартной библиотеке, 1 раз накодь своё.
Re[5]: Java Web Start+передача класса по сети ClassCirculari
Здравствуйте, Волк-Призрак, Вы писали:
D>>Опиши проблему со Swing'ом, из-за которой ты решил передавать классы по сети таким образом. ВП>Сначала я передавал Swing-формы как есть, и принимая, проверял объекты на instanceof. ВП>Но так как swing не приспособлен для long term persistence, согласно документации... ВП>Это выглядело как ошибка при приёме объекта, про разные serial у класса javax.swing.JComponent. — т.е. JComponent в 1.3.1 (версиимя в которой компилирую и запускаю сервер) и в 1.4.2.06 (версия где запускается клиент). ВП>Мне нужна защита от "разных версий свинга" у сервера и у клиента.
А java.beans.XMLEncoder/java.beans.XMLDecoder не подошел?
--
Дмитро
Re[6]: Java Web Start+передача класса по сети ClassCirculari
Здравствуйте, Lucker, Вы писали:
D>>А java.beans.XMLEncoder/java.beans.XMLDecoder не подошел?
L>Так у него в одном месте 1.3 стоит. Надо еще парсер цеплять клиентам
Во ляпнул. Там не парсер, там 1.4 надо цеплять, штоб заработало. Тогда нах-ра java.beans.XMLEncoder/java.beans.XMLDecoder?
Здравствуйте, Lucker, Вы писали:
L>Здравствуйте, Lucker, Вы писали:
D>>>А java.beans.XMLEncoder/java.beans.XMLDecoder не подошел?
L>>Так у него в одном месте 1.3 стоит. Надо еще парсер цеплять клиентам
L>Во ляпнул. Там не парсер, там 1.4 надо цеплять, штоб заработало. Тогда нах-ра java.beans.XMLEncoder/java.beans.XMLDecoder?
И то правда! С java.beans.XMLEncoder/java.beans.XMLDecoder'ами я поспешил.
--
Дмитро
Re[9]: Java Web Start+передача класса по сети ClassCirculari
Здравствуйте, dshe, Вы писали:
D>Здравствуйте, Lucker, Вы писали:
L>>Здравствуйте, Lucker, Вы писали:
D>>>>А java.beans.XMLEncoder/java.beans.XMLDecoder не подошел?
L>>>Так у него в одном месте 1.3 стоит. Надо еще парсер цеплять клиентам
L>>Во ляпнул. Там не парсер, там 1.4 надо цеплять, штоб заработало. Тогда нах-ра java.beans.XMLEncoder/java.beans.XMLDecoder?
D>И то правда! С java.beans.XMLEncoder/java.beans.XMLDecoder'ами я поспешил.
В общем, спасибо за рекомендацию.
Просто
у меня специфический протокол в системе — передаются сериализованые зипованые объекты,
производные от класса, описываюшего понятие "сообщение".
Я не знаю про этот декодер, в частности, как он отреагирует на то, что результат работы кодера
запишется в ObjectOutputStream, опирающемся на ZipOutputStream, лежащем на ByteArrayStream...
Код просто переносил из дейтаграмного варианта в сокетный. Когда дейтаграмный вариант делал,
дейтаграммы из Одессы в Ростов доходили, а с Москвой наладить связь не удалось. Вот и перешел на сокеты.
Теперь с ними проблемы (не осовобождаются все ресурсы, использованые сокетом),
Т. е. при повторном запуске клиентской программы он выдаёт BindException : address in use.
но это другая тема.
Если на этот пункт здесь реакции не будет, открою как отдельный топик.
while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
Скажи .net корпорации Microsoft! (c) ghostwolf 2004
7 раз поищи в стандартной библиотеке, 1 раз накодь своё.