Здравствуйте, 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.