Telefonino.net network
 
| HOMEPAGE | INDICE FORUM | REGOLAMENTO | ::. NEI PREFERITI .:: | RSS Forum | RSS News | NEWS web | NEWS software |
| PUBBLICITA' | | ARTICOLI | WIN XP | VISTA | WIN 7 | REGISTRI | SOFTWARE | MANUALI | RECENSIONI | LINUX | HUMOR | HARDWARE | DOWNLOAD | | CERCA nel FORUM » |

Torna indietro   WinTricks Forum > Software > Programmazione

Notices

Rispondi
 
Strumenti discussione
Vecchio 19-11-2004, 17.03.02   #1
Dav82
Gold Member
Top Poster
 
Registrato: 18-07-2002
Messaggi: 6.399
Dav82 promette bene
[Java] Caricare dinamicamente un jar e usare tutte le sue classi

Ciao a tutti

E' da un po' che sto cercando di risolvere questo problema ma non ne vengo a capo

Ho un programma Java che ha bisogno di usare delle classi contenute in dei file jar, e fin qui niente di male: basta mettere il file jar nel CLASSPATH e tutto funziona tranquillamente.
Il fatto è che devo caricare il jar a runtime, perchè questo si può trovare in un qualsiasi percorso del file system locale, quindi niente posizionamento fisso nella variabile d'ambiente CLASSPATH.
Ho provato modificando il java.class.path così:
Codice:
String oldPath = System.getProperty("java.class.path");
String newPath = oldPath + "ilMioFileJar.jar;";
System.setProperty("java.class.path", newPath);
ma niente da fare. Da qualche parte ho anche letto che così non può funzionare perchè si produrrebbe solo una copia modificata del CLASSPATH originale e il classloader se ne frega di questa copia e usa sempre il CLASSPATH originale.

Ho quindi ben pensato di usare la classe URLClassLoader.
Finchè devo caricare una sola classe niente di male, il problema viene propio con i jar. Ecco il codice che ho usato:
Codice:
File f = new File("ilMioFileJar.jar");
//creo un array contenente l'url del mio file jar
URL[] url = new URL[]{f.toURL()};

//lo do in pasto al classloder
URLClassLoader mioCL = new URLClassLoader(url);

//piglio la classe che mi serve istanziare
Class c = mioCL.loadClass("ClasseCheMiServe");

//prendo un'istanza della classe
TipoDellaClasse tdc = (TipoDellaClasse)c.newInstance()

//e adesso uso la classe!
Tutto bene fino alla fine, ma al momento di usare la classe, la quale usa altre classi presenti nel jar, sorge il problema: sembra che non riesca a fare il loading di altre classi che gli servono e che sono contenute nel jar.
Mi viene restituito un errore del tipo "mi manca la classe pack1.pack2.ClasseX" e allora ho provato anche a fare il loading preventivo di questa classe:

Codice:
//piglio la classe che mi serve istanziare
Class c = mioCL.loadClass("ClasseCheMiServe");

//piglio la classe che mi viene segnalata nell'errore
Class d = mioCL.loadClass("pack1.pack2.ClasseX");

//prendo un'istanza della classe
TipoDellaClasse tdc = (TipoDellaClasse)c.newInstance()

//e adesso uso la classe!
ma nulla cambia: mi viene restituito sempre lo stesso errore.

Come faccio?
C'è un modo per fare il loading "completo" di un jar, o un modo per fare caricare dinamicamente le classi presenti nel jar in caso di necessità?

Oppure il problema va affrontato con l'uso di altre classi?

Resta sempre il vincolo che il .jar non può essere specificato nella variabile di sistema CLASSPATH, poichè l'utente (bastardo) può decidere di metterlo dove vuole sul proprio disco e me lo indica con una bella finestrella di dialogo durante l'esecuzione del programma.

Se non avete capito qualcosa perchè mi sono espresso male (sicuro!) chiedetemi pure

Grazie a tutti

Dav82 non è collegato   Rispondi citando
Vecchio 19-11-2004, 17.47.33   #2
P8257 WebMaster
Gold Member
 
Registrato: 07-01-2002
Loc.: Milano
Messaggi: 2.863
P8257 WebMaster promette bene
Ciao Dav,
complimenti per le soluzioni che hai cercato ed utilizzato... anch'io spesso ho questo tipo di problemi e non mi è mai piaciuto il sistema di "deploy" di Java (se devo essere proprio sincero...)

Quindi volevo cheiderti:
In che momento l'utente ti specifica questo Jar? .. All'inizio dell'esecuzione del tuo programma? .. In fase di installazione? .. oppure proprio mentre lo sta usando?...

E anche un'altra cosa: E' possibile spezzare il programma in due... ?

Poi ti spiego cosa ho in mente...

Bye
P8257 WebMaster non è collegato   Rispondi citando
Vecchio 19-11-2004, 18.13.21   #3
Dav82
Gold Member
Top Poster
 
Registrato: 18-07-2002
Messaggi: 6.399
Dav82 promette bene
Ciao Web, grazie

Il programma principale parte, l'utente può, tramite menu, indicarmi il file jar da utilizzare (un programma esterno a cui devo dare in pasto dei dati e che mi fornisce, ovviamente, delle risposte), e io da quel punto in poi devo poter utilizzare il jar indicatomi.

Nel mio programma sono già presenti le classi che gestiscono le classi del jar: in sostanza, per ogni jar che l'utente può caricarmi, ho una classe GestoreJarX che sa come utilizzare il jar; sono presenti quindi tanti piccoli plugin implemenati dalle classi GestoreJarX che possono essere utilizzati una volta indicato il jar da utilizzare per il plugin specifico (io ovviamente in fase di compilazione ho tutti i jar impostati nelle variabili d'ambiente di NetBeans, quindi non ho problemi di sorta).

Una volta che l'utente mi indica il percorso dove trovare il jar, me lo salvo in un file di configurazione e al successivo riavvio dell'applicazione uso sempre lo stesso percorso. L'utente può cambiare anche il percorso di un jar per uno dei plugin, e io devo adattarmi al cambiamento.

Che cosa intendi per "spezzare il programma in due"?
Perchè così è, volendo, già spezzettato: c'è il programma principale con le sue funzionalità, il gestore di tutti i plugin GestorePlugin che si integra nel programma principale, e i vari plugin GestoreJarX che si "registrano" presso il GestorePlugin.

Io posso intervenire da GestorePlugin in giù, perchè mi occupo solo di questo.

Grazie

Ultima modifica di Dav82 : 19-11-2004 alle ore 18.20.24
Dav82 non è collegato   Rispondi citando
Vecchio 19-11-2004, 20.06.37   #4
Dav82
Gold Member
Top Poster
 
Registrato: 18-07-2002
Messaggi: 6.399
Dav82 promette bene
Adesso funziona

Giuro, non ho cambiato niente


La cosa bella è invece che ho un attributo privato di una classe che viene posto uguale a un certo valore nel costruttore, nella classe non ci sono altre istruzioni che toccano sto attributo privato, eppure a un certo punto me lo ritrovo cambiato!
Beh... tolto assegnamento nel costruttore, messo nella dichiarazione dell'attributo e aggiunto un bel final all'attributo stesso e adesso non cambia più...

Sembra... sembra funzionare!

Adesso provo a farlo girare un po' (leggasi: testing alla carlona ) con tutti i plugin e vedo come va

Web, tieniti pronto che fra un po' sicuramente mi crasha tutto e sono ancora qui!
Dav82 non è collegato   Rispondi citando
Vecchio 19-11-2004, 21.02.17   #5
Dav82
Gold Member
Top Poster
 
Registrato: 18-07-2002
Messaggi: 6.399
Dav82 promette bene
No scherzavo, non funziona. C'era una bella cartella scompattata in un percorso che avevo nel classpath

Cmq, nel mio jar c'è sta roba:

Codice:
mioJar.jar
   |
   |---- pack1
           |
           |----sottopack1
                    |
                    |---- customException.class
e mi viene restituito l'errore:

java.lang.NoClassDefFoundError: pack1/sottopack1/customException

Però l'operazione di loading della classe customException con mioCL.loadClass("pack1.sottopack1.customException" ) va a buon fine, non mi solleva eccezioni: quindi il mioCL riesce a "vedere" che la classe esiste...
Dav82 non è collegato   Rispondi citando
Vecchio 20-11-2004, 01.54.54   #6
P8257 WebMaster
Gold Member
 
Registrato: 07-01-2002
Loc.: Milano
Messaggi: 2.863
P8257 WebMaster promette bene
Ok bene,
se ho capito bene, l'utente sceglie il jar da utilizzare e tu scrivi la preferenza in un file di configurazione che poi vai ad utilizzare nelle successive sessioni...

Volendo essere sbrigativi e un po' grezzi, potrei suggerirti due metodi:

1 - "spezzi" il programma, ovvero, la parte in cui l'utente decide il jar da utilizzare termina la sua esecuzione una volta che è stata effettuata la scelta eseguendo due operazioni: scrivendo il file di configurazione (come già fa) e creando uno startup (ad esempio un .bat) ad hoc per lanciare l'altra parte del programma con il classpath corretto, infine si preoccupa di lanciare il bat appena creato dando all'utente la sensazione di "continuità" del programma, mentre in realtà il vero e proprio applicativo parte ora...

2 - Dopo la selezione dell'utente prelevi il jar dal path che ti ha indicato e lo estrai in una tua cartella temporanea settata in maniera statica nel tuo classpath oppure caricando le classi dinamicamente come hai già fatto nel tuo esempio; questo ti permette di usare un percorso fisso e di non dover utilizzare il jar ma solo i .class così estratti.
Quando l'utente cambia la preferenza, tu svuoti la cartella temporanea per poterci estrarre dentro un altro jar...

Tutto questo, posto per assodato che io abbia afferrato il tuo ragionamento ...

Per altre soluzioni più "professionali" ti rimando a domani, dopo una sana dormita...

Bye
P8257 WebMaster non è collegato   Rispondi citando
Vecchio 20-11-2004, 03.32.44   #7
Dav82
Gold Member
Top Poster
 
Registrato: 18-07-2002
Messaggi: 6.399
Dav82 promette bene
Grazie Web (Y)

Devo pensar bene come applicare le due soluzioni... la prima è forse più problematica... la seconda è forse più semplice.... ma è tardi, una bella dormita fa sicuramente bene anche a me

Così riesco anche a spiegarti meglio sta architettura del cavolo!
Dav82 non è collegato   Rispondi citando
Vecchio 20-11-2004, 13.59.34   #8
Dav82
Gold Member
Top Poster
 
Registrato: 18-07-2002
Messaggi: 6.399
Dav82 promette bene
Mo ti spiego!
Facciamo conto che l'applicazione più grande abbia a disposizione un testo scritto in italiano. Io mi occupo dello strumento "Traduzione", che consta di molti plugin: traduzione in inglese, tedesco, francese, spagnolo, latino ecc ecc. Io ho una classe per ogni traduttore, e ognuna di queste classi sa come utilizzare un determinato jar (di terze parti) per ottenere la traduzione di un testo nella lingua supportata dal jar. L'applicazione viene però distribuita senza i jar, è l'utente che si deve preoccupare di reperirli e indicare al mio strumento "Traduzione" dove beccare i jar corretti.
Mettiamo che l'utente abbia indicato allo strumento dove trovare i jar per Inglese, Tedesco e Francese. In fase di esecuzione, può chiedere la traduzione anche solamente con Tedesco e Francese: tutti i plugin di cui è stato indicato il jar devono però essere attivi per poter essere richiamati.

Quindi potrei fare così: siccome so, in fase di startup, quanti plugin al massimo sono supportati, posso riservarmi di impostare un classpath così:

SET CLASSPATH = %CLASSPATH%; C:\MioProg\Traduzione\plug1.jar; C:\MioProg\Traduzione\plug3.jar; C:\MioProg\Traduzione\plug2.jar; C:\MioProg\Traduzione\plug4.jar;Ecc.Ecc;

e per ogni jar che l'utente mi indica io piglio il jar e lo copio rinominato come plugX.jar e a sto punto lo posso usare.
E' un po' dispendioso perchè devo copiarmi un bel po' di file, e poi il bello è che alcuni plugin sono composti da più jar... e non saprei come fare

Posso anche seguire un'altra strategia: nel classpath, al posto di riservarmi i jar, mi riservo delle cartelle, una per ogni plugin, in cui copiare e scompattare i jar e da lì usarli, come mi hai detto tu... devo vedere se è una cosa fattibile come dimensioni in MB: tutto il programma occupa 3MB di Jar, e rischio con questa tecnica di usare qualche decina di MB per i Jar dei plugin scompattati...

edit: ho appena provato con uno dei plugin che consta di 19 jar ( ): jarrati occupano 3MB, scompattati sono più di 7MB (per 12MB di spazio su disco col mio FS). Per fortuna così sono solo due su sette: cinque sono invece composti da un unico jar.

riedit: non ho dormito abbastanza! Se anche indicavo solo il jar "padre" di tutti di un determinato plugin nel classpath, tutto funzionava a meraviglia, perchè risolveva lui le dipendenze in non so che modo. Quindi mi basta copiare tutti i jar di tutti i plugin nella cartella C:\MioProg\Traduzione e mettere nel CP solo i jar "padri" dei plugin, quindi uno per ogni plugin (almeno a occhio e croce)


Dai, adesso (dopo pranzo) provo a vedere quanto tempo ci mette su un pc dalle prestazioni decenti e non come il mio portatile, e vediamo se sono accettabili

Ultima modifica di Dav82 : 20-11-2004 alle ore 14.07.23
Dav82 non è collegato   Rispondi citando
Vecchio 20-11-2004, 14.22.33   #9
Dav82
Gold Member
Top Poster
 
Registrato: 18-07-2002
Messaggi: 6.399
Dav82 promette bene
Quota:
Originariamente inviato da Dav82
Quindi mi basta copiare tutti i jar di tutti i plugin nella cartella C:\MioProg\Traduzione e mettere nel CP solo i jar "padri" dei plugin, quindi uno per ogni plugin (almeno a occhio e croce)
Eh no
Ci sono due plugin diversi che hanno un jar chiamato con lo stesso nome

Ok, faccio così: creo tante cartelle C:\MioProg\Traduzione\PluginX, in ognuna ci copio tutti i jar di un plugin e inserisco nel classpath tanti C:\MioProg\Traduzione\PluginX\JarPadrePluginX.jar

E che cavolo!!!
Dav82 non è collegato   Rispondi citando
Vecchio 06-12-2004, 21.14.17   #10
Dav82
Gold Member
Top Poster
 
Registrato: 18-07-2002
Messaggi: 6.399
Dav82 promette bene
Webbbbbbbbbbbbb, mi ero scordato che ho risolto!

Siccome con i classloader non sono riuscito a cavarci niente, ho usato la reflection e via

Grassie mille (Y)
Dav82 non è collegato   Rispondi citando
Rispondi


Utenti attualmente attivi che stanno leggendo questa discussione: 1 (0 utenti e 1 ospiti)
 
Strumenti discussione

Regole di scrittura
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is ON
Gli smilies sono ON
[IMG] è ON
Il codice HTML è OFF

Vai al forum

Discussioni simili
Discussione Autore discussione Forum Risposte Ultimo messaggio
posso usare un disco di ripristino di un parkard bell su un altro parkard bell? ilveroenk1 Windows 7/Vista/XP/ 2003 6 07-12-2007 13.33.58
posso usare un disco di ripristino di un parkard bell su un altro parkard bell? ilveroenk1 Linux e altri Sistemi Operativi 1 07-12-2007 11.17.58
posso usare un disco di ripristino di un parkard bell su un altro parkard bell? ilveroenk1 Software applicativo 1 07-12-2007 11.17.46
usare solo il browser backgroundit Windows 7/Vista/XP/ 2003 10 10-09-2007 13.02.04
Dubbio su quale cd usare per ripristino sistema: cd drivers o i cd di ripristino?? Fabius250485 Windows 7/Vista/XP/ 2003 2 31-05-2006 13.23.11

Orario GMT +2. Ora sono le: 03.10.57.


E' vietata la riproduzione, anche solo in parte, di contenuti e grafica.
Copyright © 1999-2017 Edizioni Master S.p.A. p.iva: 02105820787 • Tutti i diritti sono riservati
L'editore NON si assume nessuna responsabilità dei contenuti pubblicati sul forum in quanto redatti direttamente dagli utenti.
Questi ultimi sono responsabili dei contenuti da loro riportati nelle discussioni del forum
Powered by vBulletin - 2010 Copyright © Jelsoft Enterprises Limited.