Ciao a tutti,
spero di essere nella sezione giusta.
La mia domanda è questa: volevo sapere come si può caricare a runtime una classe java presente magari in un jar.
Grazie mille!!!
Ciao a tutti,
spero di essere nella sezione giusta.
La mia domanda è questa: volevo sapere come si può caricare a runtime una classe java presente magari in un jar.
Grazie mille!!!
Se il jar è già in "classpath" e sai il nome qualificato della classe da caricare, basta il classico forName() di java.lang.Class.Originariamente inviato da enfix86
La mia domanda è questa: volevo sapere come si può caricare a runtime una classe java presente magari in un jar.
Se il jar non è già in classpath ma vuoi poter fare una gestione in stile "a plug-in", ovvero trovare dei jar in una certa directory nota e caricare "qualcosa" (poi cosa "sai" della classe o come eventualmente la "scopri" è un altro discorso), serve altro (si parte generalmente da un URLClassLoader).
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
La gestione che volevo fare è proprio come dici tu, una sorta di plugin che viene aggiunto.
Dopo infatti mi servirebbe anche recuperare la classe che implementa un certo tipo di interfaccia.
Come posso fare entrambe le cose ?
Potresti farmi un esempio con del codice magari.
Le questioni sono svariate per fare una cosa del genere.Originariamente inviato da enfix86
La gestione che volevo fare è proprio come dici tu, una sorta di plugin che viene aggiunto.
Dopo infatti mi servirebbe anche recuperare la classe che implementa un certo tipo di interfaccia.
Come posso fare entrambe le cose ?
Innanzitutto la applicazione deve sapere di dover scansionare una (o più) directory "note" al fine di rintracciare i plugin. Basterebbe stabilire ad esempio che un plugin è un file che si può chiamare come si vuole purché con estensione .jar che sia "depositato" in quella/e directory.
Per gestire il caricamento si deve usare un apposito "class loader" e in genere si può usare java.net.URLClassLoader. Ma il problema non è tanto questo.
La vera questione è: cosa andare a cercare a livello di classi?
Forzare e imporre a tutti i plugin di avere una certa classe con un nome ben preciso sarebbe possibile (a patto di usare class loader distinti). Ma sarebbe comunque poco bello e poco pratico.
La cosa migliore sarebbe quella di avere nel pacchetto del plugin un qualcosa che fornisce delle "meta informazioni" sul plugin. Tra cui che so ... nome del plugin, autore, ecc... compresa la indicazioni di quale/i classe/i caricare.
Tutto questo potrebbe essere descritto in vari modi: con un file XML, con un file di properties o magari messo tra gli attributi del "manifest" del jar.
Se la applicazione si chiama japp si potrebbe ad esempio stabilire che nel jar del plugin alla "radice" ci deve essere un japp-plugin.xml che è il descrittore del plugin.
Si può fare come si vuole, non ci sono vincoli particolari né standard veri e propri. La applicazione una volta che ha composto il pathname al jar del plugin potrebbe aprirlo (un jar è uno zip) con le classi del package standard java.util.zip o java.util.jar e andare a cercare il "descrittore" (qualunque cosa sia).
Una volta che la applicazione ha determinato un nome di classe da caricare, tramite URLClassLoader e ancora con forName() di Class potrebbe ottenere finalmente il Class della classe (e istanziarla).
Tale classe dovrebbe implementare una interfaccia, che rappresenta il "ponte" o meglio dire il "contratto" tra la applicazione e i plugin. Tramite tale interfaccia il plugin potrebbe ricevere oggetti e/o "esporre" lui oggetti per fornire alla applicazione le funzionalità in più che implementa.
Anche questo è comunque tutto da stabilire in base alla applicazione e a cosa i plugin possono/devono fare. Non ci sono standard in questo senso.
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
Ok, ho fatto una cosa del genere, optando per ora con lo stesso nome (lo so ke non è il massimo), ma ho problemi a caricare la classe del .jar.
Ho visto questo esempio ma non capisco alcune cose:
La classe da caricare si chiama sempre Algoritmo e l'ho messa su loadClass("Algoritmo").codice:Class cls = null; Object o=null; String path = "memorysim\\kernel\\algo\\"; //percorso dove vengono messi i jar File dir = new File (path); /*-- filtro per i file .jar --*/ FileExtFilter fef = new FileExtFilter("jar"); String[] list = dir.list (fef); /*-- elenca tutti i file con quella estensione --*/ for (int i = 0; i < list.length; i++) { //System.out.println(list[i]); try { File file = new File(path+list[i]); URL url = file.toURI().toURL(); URL[] urls = new URL[]{url}; ClassLoader cl = new URLClassLoader(urls); cls = cl.loadClass("Algoritmo"); //nome classe da caricare o = cls.newInstance(); if(o instanceof Algoritmo){ Algoritmo algoritmo = (Algoritmo) o; algoritmi.add(algoritmo); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); }}
Il problema è che in realtà ho notato che non carica la classe dentro il jar.
Come posso fare ?
Mi è venuto in mente però che forse quello che sto facendo è sbagliato di principio.
Infatti io dovrei caricare il jar ma anche tutte le sue classi dovrebbero essere caricate per poter essere utilizzate.
Il mio sistema si interfaccia con una sola classe del plugin, che però utilizza altre classi.
Come devo fare ?
Caricare in class path tutto il jar o mi basta solo la classe che utilizzo io ?
Spero di essere stato chiaro.....
Non vedo il problema. Se la prima classe (e la sua istanza) "tirata fuori" in modo dinamico dalla applicazione andrà ad istanziare qualunque altro tipo presente nel jar ... viene caricato in automatico.Originariamente inviato da enfix86
Infatti io dovrei caricare il jar ma anche tutte le sue classi dovrebbero essere caricate per poter essere utilizzate.
Il mio sistema si interfaccia con una sola classe del plugin, che però utilizza altre classi.
La vera questione è appunto solo quella di legare i plugin alla applicazione, possibilmente tramite interfacce e facendo in modo che la "conoscenza" tra le due parti sia la minima/sufficiente per quello che si deve fare.
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
Si hai ragione, ho visto che infatti funziona.
Pensavo non andasse.
Comunque siccome ho visto che l'idea dello stesso nome per la classe "principale" all'interno del jar non è un grankè, avresti da suggerirmi un semplice modo per trovare qual'è la classe che implementa l'interfaccia comune.
L'unica possibilità è andare a parsare un xml ?
Pensavo se no ad un metodo che scansiona il jar e cerca quale classe è quella che implementa l'interfaccia (supponendo stia nella root del jar e non in qualche sottocartella).
Io ho parlato in precedenza in generale di "meta informazioni" sul plugin. Poter avere un "descrittore" del plugin che può descriverlo in modo più o meno ampio.Originariamente inviato da enfix86
L'unica possibilità è andare a parsare un xml ?
Può essere tecnicamente qualunque cosa. Un file in formato XML con una struttura inventata da te con un nome "noto" che deve trovarsi in una cartella nota del jar. Oppure un file di properties. Oppure ancora inserire le informazioni come attributi speciali nel "manifest" del jar (le classi nel package java.util.jar possono gestire il manifest).
Devi solo scegliere .... non ci sono standard o vincoli particolari.
Tecnicamente è fattibile. Basta usare le classi in java.util.zip/jar per "enumerare" i file e trovare i .class.Originariamente inviato da enfix86
Pensavo se no ad un metodo che scansiona il jar e cerca quale classe è quella che implementa l'interfaccia (supponendo stia nella root del jar e non in qualche sottocartella).
Il fatto che vuoi restringere la selezione solo ai file alla "radice" può anche essere accettabile. Tieni solo presente che un .class alla radice vuol dire che non ha package, che comunque non vuol dire nulla di strano.
E chiaramente, altra cosa importante, ci deve essere un class loader specifico per ciascuno dei jar.
Andrea, andbin.dev – Senior Java developer – SCJP 5 (91%) • SCWCD 5 (94%)
java.util.function Interfaces Cheat Sheet — Java Versions Cheat Sheet
Quello di inserire informazioni sul manifest sarebbe l'ideale.
Mi potresti dire come faccio a "leggere" dopo questa info, magari con un esempio pratico.