morskott
23-02-2008, 19:55
Salve, avrei bisogno di passare un oggetto di tipo Class tra un server e un client. ho provato prima di tutto a fare un esempio banaleimport java.net.*;
import java.io.*;
public class TestClassLoader{
public static void main(String[] args) throws Exception{
final String className=args[0];
ServerSocket ss=new ServerSocket(333);
Thread t1=new Thread(new Runnable(){
public void run(){
try{
Class<?> cc=Class.forName(className);
System.out.println("CLIENT:"+cc.toString());
Socket s=new Socket("localhost",333);
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
System.out.println("CLIENT:ObjectOutputStream aperto");
oos.writeObject(cc);
oos.flush();
System.out.println("CLIENT:Oggetto mandato");
oos.close();
s.close();
}catch(Exception ex) {System.out.println("NONONO "+ex.toString());}
}
});
t1.start();
Socket s=ss.accept();
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
System.out.println("SERVER:ObjectInputStream aperto");
Class<?> received=(Class<?>)ois.readObject();
ois.close();
s.close();
ss.close();
System.out.println("SERVER:Classe ricevuta, nome:"+received.getName());
}
}e funziona, ma quando vado ad immergere il codice nel problema reale mi da errore di java.rmi.UnmarshalException: error unmarshalling return, il codice del Server è private Class<?> transferFromRemote(String name,InetAddress addr) throws ClassNotFoundException{
try {
Socket s = new Socket(addr, 666);
PrintWriter pw = new PrintWriter(s.getOutputStream());
pw.println(name); //trasferisco il nome della classe
pw.flush();
InputStreamReader isr=new InputStreamReader(s.getInputStream());
BufferedReader br=new BufferedReader(isr);
if (!br.readLine().equals("SI")){ //MODIFICATO
br.close();
isr.close();
s.close();
System.out.println("il Client non conosce la classe");
throw new ClassNotFoundException(name);
}
System.out.println("Il Client conosce la classe");
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
System.out.println("ObjectInputStream creato");
Class<?> ret=(Class<?>) ois.readObject();
System.out.println("Classe ricevuta, addio");
pw.close();
br.close();
isr.close();
ois.close();
s.close();
return ret;
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
throw new ClassNotFoundException(name);
}
} mentre il codice del client è public void run(){
try {
System.out.println("Richiesta Classe ricevuta");
InputStreamReader isr = new InputStreamReader(this.s.getInputStream());
BufferedReader br = new BufferedReader(isr);
String nomeClasse = br.readLine(); //mi prendo il nome della classe
System.out.println("Nome classe Ricevuto (" + nomeClasse + ")");
PrintWriter pw=new PrintWriter(s.getOutputStream());
try{
Class<?> toSend=Class.forName(nomeClasse);
pw.println("SI");
pw.flush();
System.out.println("Conosco la calsse, la mando");
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
System.out.println("ObjectOutputStream creato, classe ("+toSend.getName()+")");
oos.writeObject(toSend);
oos.flush();
System.out.println("Classe mandata, chiudo tutto");
oos.close();
pw.close();
br.close();
isr.close();
s.close();
} catch (ClassNotFoundException ex){
pw.println("NO");
pw.flush();
pw.close();
br.close();
isr.close();
s.close();
}
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}nel client la variabile s è di tipo Socket ed il metodo è dentro un Runnable avviato come nuovo thread, il problema si presenta nel fatto che la System.out.println("ObjectInputStream creato"); la stampa mentre la System.out.println("Classe ricevuta, addio"); no (nel server) mentre nel client stampa fino all'ultima System.out. Ribadisco che la classe TestClassLoader funziona normalmente!!! (Il codice concettualmente è uguale)
Altra cosa che non mi spiego è il java.rmi.UnmarshalException , il codice del server è messo dentro un ClassLoader moddato che dovrebbe caricare la classe non locale (e correttamente settato come ClassLoader) e il metodo che andrebbe a chiamare il classloader (indirettamente off course) è chiamato tramite RMI, qualche lume?
import java.io.*;
public class TestClassLoader{
public static void main(String[] args) throws Exception{
final String className=args[0];
ServerSocket ss=new ServerSocket(333);
Thread t1=new Thread(new Runnable(){
public void run(){
try{
Class<?> cc=Class.forName(className);
System.out.println("CLIENT:"+cc.toString());
Socket s=new Socket("localhost",333);
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
System.out.println("CLIENT:ObjectOutputStream aperto");
oos.writeObject(cc);
oos.flush();
System.out.println("CLIENT:Oggetto mandato");
oos.close();
s.close();
}catch(Exception ex) {System.out.println("NONONO "+ex.toString());}
}
});
t1.start();
Socket s=ss.accept();
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
System.out.println("SERVER:ObjectInputStream aperto");
Class<?> received=(Class<?>)ois.readObject();
ois.close();
s.close();
ss.close();
System.out.println("SERVER:Classe ricevuta, nome:"+received.getName());
}
}e funziona, ma quando vado ad immergere il codice nel problema reale mi da errore di java.rmi.UnmarshalException: error unmarshalling return, il codice del Server è private Class<?> transferFromRemote(String name,InetAddress addr) throws ClassNotFoundException{
try {
Socket s = new Socket(addr, 666);
PrintWriter pw = new PrintWriter(s.getOutputStream());
pw.println(name); //trasferisco il nome della classe
pw.flush();
InputStreamReader isr=new InputStreamReader(s.getInputStream());
BufferedReader br=new BufferedReader(isr);
if (!br.readLine().equals("SI")){ //MODIFICATO
br.close();
isr.close();
s.close();
System.out.println("il Client non conosce la classe");
throw new ClassNotFoundException(name);
}
System.out.println("Il Client conosce la classe");
ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
System.out.println("ObjectInputStream creato");
Class<?> ret=(Class<?>) ois.readObject();
System.out.println("Classe ricevuta, addio");
pw.close();
br.close();
isr.close();
ois.close();
s.close();
return ret;
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
throw new ClassNotFoundException(name);
}
} mentre il codice del client è public void run(){
try {
System.out.println("Richiesta Classe ricevuta");
InputStreamReader isr = new InputStreamReader(this.s.getInputStream());
BufferedReader br = new BufferedReader(isr);
String nomeClasse = br.readLine(); //mi prendo il nome della classe
System.out.println("Nome classe Ricevuto (" + nomeClasse + ")");
PrintWriter pw=new PrintWriter(s.getOutputStream());
try{
Class<?> toSend=Class.forName(nomeClasse);
pw.println("SI");
pw.flush();
System.out.println("Conosco la calsse, la mando");
ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
System.out.println("ObjectOutputStream creato, classe ("+toSend.getName()+")");
oos.writeObject(toSend);
oos.flush();
System.out.println("Classe mandata, chiudo tutto");
oos.close();
pw.close();
br.close();
isr.close();
s.close();
} catch (ClassNotFoundException ex){
pw.println("NO");
pw.flush();
pw.close();
br.close();
isr.close();
s.close();
}
} catch (IOException ex) {
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
}
}nel client la variabile s è di tipo Socket ed il metodo è dentro un Runnable avviato come nuovo thread, il problema si presenta nel fatto che la System.out.println("ObjectInputStream creato"); la stampa mentre la System.out.println("Classe ricevuta, addio"); no (nel server) mentre nel client stampa fino all'ultima System.out. Ribadisco che la classe TestClassLoader funziona normalmente!!! (Il codice concettualmente è uguale)
Altra cosa che non mi spiego è il java.rmi.UnmarshalException , il codice del server è messo dentro un ClassLoader moddato che dovrebbe caricare la classe non locale (e correttamente settato come ClassLoader) e il metodo che andrebbe a chiamare il classloader (indirettamente off course) è chiamato tramite RMI, qualche lume?