È ansible “aggiungere” a classpath in modo dinamico in java?

java -classpath ../classs;../jar;. parserTester 

Come posso ottenere la funzionalità nel comando sopra programmaticamente? Come, è ansible eseguire come:

 java parserTester 

e ottieni lo stesso risultato? Ho provato a usare URLClassLoader ma modifica il classpath e non lo aggiunge.

Grazie!


Grazie per la risposta Milhous. Ma questo è quello che sto cercando di fare .. Come è ansible ottenere prima il jar nel classpath? Ho provato a usare anche un classloader personalizzato 🙁

Funziona .. Ma mi dispiace che ho bisogno di eseguirlo solo come: java parserTester Vorrei sapere se è ansible una cosa del genere ???

    Deve essere così bcoz ho parserTester.java e. Class in una cartella separata. Ho bisogno di mantenere la struttura del file. Il parserTester utilizza un jar in una cartella jar separata.

    Puoi utilizzare java.net.URLClassLoader per caricare classi con qualsiasi elenco di URL definito dal programma che desideri:

    public class URLClassLoader estende SecureClassLoader

    Questo programma di caricamento classi viene utilizzato per caricare classi e risorse da un percorso di ricerca di URL che fanno riferimento a file e directory JAR. Si presume che ogni URL che termina con un ‘/’ si riferisca a una directory. In caso contrario, si presume che l’URL faccia riferimento a un file JAR che verrà aperto secondo necessità.

    Verrà utilizzato AccessControlContext del thread che ha creato l’istanza di URLClassLoader durante il caricamento successivo di classi e risorse.

    Le classi caricate sono per impostazione predefinita l’authorization concessa solo per accedere agli URL specificati quando è stato creato URLClassLoader.

    Dal: 1.2

    E un piccolo gioco di fantasia può estenderlo per supportare l’uso di nomi di percorso con caratteri jolly per raccogliere intere directory di JAR (questo codice ha alcuni riferimenti a metodi di utilità, ma la loro implementazione dovrebbe essere ovvia nel contesto):

     /** * Add classPath to this loader's classpath. * 

    * The classpath may contain elements that include a generic file base name. A generic basename * is a filename without the extension that may begin and/or end with an asterisk. Use of the * asterisk denotes a partial match. Any files with an extension of ".jar" whose base name match * the specified basename will be added to this class loaders classpath. The case of the filename is ignored. * For example "/somedir/*abc" means all files in somedir that end with "abc.jar", "/somedir/abc*" * means all files that start with "abc" and end with ".jar", and "/somedir/*abc*" means all files * that contain "abc" and end with ".jar". * */ public void addClassPath(String cp) { String seps=File.pathSeparator; // separators if(!File.pathSeparator.equals(";")) { seps+=";"; } // want to accept both system separator and ';' for(StringTokenizer st=new StringTokenizer(cp,seps,false); st.hasMoreTokens(); ) { String pe=st.nextToken(); File fe; String bn=null; if(pe.length()==0) { continue; } fe=new File(pe); if(fe.getName().indexOf('*')!=-1) { bn=fe.getName(); fe=fe.getParentFile(); } if(!fe.isAbsolute() && pe.charAt(0)!='/' && pe.charAt(0)!='\\') { fe=new File(rootPath,fe.getPath()); } try { fe=fe.getCanonicalFile(); } catch(IOException thr) { log.diagln("Skipping non-existent classpath element '"+fe+"' ("+thr+")."); continue; } if(!GenUtil.isBlank(bn)) { fe=new File(fe,bn); } if(classPathElements.contains(fe.getPath())) { log.diagln("Skipping duplicate classpath element '"+fe+"'."); continue; } else { classPathElements.add(fe.getPath()); } if(!GenUtil.isBlank(bn)) { addJars(fe.getParentFile(),bn); } else if(!fe.exists()) { // s/never be due getCanonicalFile() above log.diagln("Could not find classpath element '"+fe+"'"); } else if(fe.isDirectory()) { addURL(createUrl(fe)); } else if(fe.getName().toLowerCase().endsWith(".zip") || fe.getName().toLowerCase().endsWith(".jar")) { addURL(createUrl(fe)); } else { log.diagln("ClassPath element '"+fe+"' is not an existing directory and is not a file ending with '.zip' or '.jar'"); } } log.diagln("Class loader is using classpath: \""+classPath+"\"."); } /** * Adds a set of JAR files using a generic base name to this loader's classpath. See @link:addClassPath(String) for * details of the generic base name. */ public void addJars(File dir, String nam) { String[] jars; // matching jar files if(nam.endsWith(".jar")) { nam=nam.substring(0,(nam.length()-4)); } if(!dir.exists()) { log.diagln("Could not find directory for Class Path element '"+dir+File.separator+nam+".jar'"); return; } if(!dir.canRead()) { log.error("Could not read directory for Class Path element '"+dir+File.separator+nam+".jar'"); return; } FileSelector fs=new FileSelector(true).add("BaseName","EG",nam,true).add("Name","EW",".jar",true); if((jars=dir.list(fs))==null) { log.error("Error accessing directory for Class Path element '"+dir+File.separator+nam+".jar'"); } else if(jars.length==0) { log.diagln("No JAR files match specification '"+new File(dir,nam)+".jar'"); } else { log.diagln("Adding files matching specification '"+dir+File.separator+nam+".jar'"); Arrays.sort(jars,String.CASE_INSENSITIVE_ORDER); for(int xa=0; xa0) { classPath+=File.pathSeparator; } this.classPath+=fe.getPath(); return url; } catch(MalformsdURLException thr) { log.diagln("Classpath element '"+fe+"' could not be used to create a valid file system URL"); return null; } }

    È ansible implementare il proprio programma di caricamento classi , ma quella class / jar deve trovarsi nel classpath per essere eseguita.

    provare

     java -cp *.jar:. myClass 

    o

     export CLASSPATH=./lib/tool.jar:. java myClass 

    o

     java -jar file.jar 

    Devo essere d’accordo con gli altri due poster, sembra che tu stia complicando una class di test. Non è così inusuale avere i file .java e .class in cartelle separate, mentre a seconda dei file jar in ancora un terzo, senza modificare a livello di codice il classpath. Se lo fai perché non vuoi dover digitare il classpath sulla riga di comando ogni volta, ti suggerisco uno script di shell o un file batch. Meglio ancora, un IDE. La domanda che ho davvero è: perché stai cercando di gestire il classpath nel codice?

    È ansible scrivere un file batch o un file script della shell per esportare il classpath ed eseguire il programma java. In Windows,

    imposta classpath =% classpath%; ../ classs; ../ jars / * java ParserTester

    In Unix, export classpath =% classpath%: ../ classs: ../ jars / * java ParserTester

    Se si nomina il nome del file come parser.bat o parser.sh, è sufficiente eseguirlo chiamando il parser nel rispettivo SO.

    Da java 1.6, puoi includere tutti i jar in una directory nel classpath semplicemente dicendo / *

    Se si sta tentando di generare un file java in modo dinamico, compilare e aggiungere nel classpath, impostare la directory in cui il file di class viene generato in precedenza nel classpath. Dovrebbe caricare la class. Se stai modificando la class java già generata, sostanzialmente ricompilando dopo la modifica e se vuoi caricare la nuova class, devi usare il tuo programma di caricamento classi personalizzato per evitare la memorizzazione nella cache della class.

    Ho capito bene ?! L’unico motivo per cui vuoi avviare la tua class senza specificare il classpath e caricarlo in fase di runtime? …

    parserTester java

    invece di

    java -classpath ../classs;../jar ;. parserTester

    Probabilmente non ho avuto la tua ragione. Ma se “quello è” ciò che vuoi puoi fare quanto segue (anche se non ha molto senso per me)

    • Avvia la class
    • Dal metodo principale, una volta un’altra class, si imposta programmaticamente il percorso di class.
    • Fine della storia

    Qualcosa come il seguente “codice java -pseudo”

     public static void main( String [] args ) { String classpath = "classs;../jar"; Runtime.getRuntime().execute("java + classpath + " parserTester "); } 

    Per favore dimmi se ho capito bene. Se vuoi fare qualcos’altro, aiuterei volentieri.

    Penso che quello che vuoi sia un “Execution Wrapper” o un “Launcher” specifico per la piattaforma … in genere questo componente viene utilizzato per rilevare il tuo SO, l’architettura e le dipendenze e quindi apportare modifiche prima di avviare l’applicazione. È un modello di progettazione old school (parlando degli anni ’80 e precedenti), ma è ancora usato molto oggi. L’idea è che il programma può essere indipendente dal sistema e dall’ambiente e il programma di avvio eseguirà i preparativi e comunicherà al software tutto ciò che è necessario sapere. Molti programmi open source moderni lo fanno con script di shell e file batch, ecc … Apache Tomcat per esempio. Potresti anche creare il wrapper in java e avviare il software con un comando da riga di comando (assicurati di aggiungere “&” alla fine del tuo comando exec in * NIX in modo che il tuo wrapper possa uscire lasciando solo il tuo software in esecuzione. .. consente anche di chiudere la finestra della shell senza uccidere il processo)

    Ottimo post, nel mio caso l’ho fatto per funzionare bene (nota: specifica per Windows):

     set classpath=%classpath%;../lib/* java -cp %classpath% com.test.MyClass