Re[2]: Java Web Start+передача класса по сети ClassCirculari
От: Волк-Призрак Россия http://ghostwolf.newmail.ru
Дата: 30.11.04 10:40
Оценка:
Здравствуйте, 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 раз накодь своё.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.