So che questo è stato chiesto e ho risposto molto ma non ho ancora una buona soluzione e ancora non capisco alcune parti. Quindi ho il requisito di compilare i file * .java a livello di codice.Compilare i file java programmaticamente
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
è quello che sto usando e (come previsto) il compilatore è null
. Ora, so che devo usare il JDK e non il JRE come "runtime", ma qui c'è qualcosa che non capisco: non è sufficiente mettere semplicemente tools.jar
nel classpath dell'applicazione e poi avere accesso all'API Java Compiler? Se questo è vero, c'è (credo che ci sia) una differenza tra un'applicazione java stand-alone e un'applicazione basata sul web. In realtà, sto tentando di richiamare JavaCompiler da una webapp di PlayFramework quindi ho capito, forse queste soluzioni (con incluso lo tools.jar
) funzionano solo per le applicazioni autonome?
Ho anche cercato di creare un ClassLoader personalizzato e richiamare il metodo di cui sopra con la riflessione, ma tutto quello che sto ottenendo è null
per l'oggetto compiler
:
ClassLoader classloader = app.classloader();
File file = new File("lib/tools.jar");
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
ClassLoader newCL = new URLClassLoader(urls, classloader) {
};
Class<?> loadClass = newCL.loadClass("javax.tools.ToolProvider");
Method method = loadClass.getMethod("getSystemJavaCompiler", null);
Object object = method.invoke(null);
System.out.println("Object: " + object); // NULL
Spiegazione per il codice precedente:
- Non ho incluso try/catches per motivi di semplicità.
- app.classloader() è un metodo che restituisce il gioco ClassLoader di App
tools.jar
è incluso nella mia cartella lib del progetto Play (questo implica che è sul classpath del progetto - in base alla documentazione gioco)
Sono quasi sicuro che c'è qualcos'altro che devo fare prima che Play sia in grado di caricare la classe del compilatore Java. Solo che non so cosa mi manca.
Opzioni come Runtime.exec("javac myFile.java")
e il compilatore JDT Eclipse sono noti a me, ma non è quello che sto cercando.
Oh, e qualcosa come System.setProperty("java.home", "PATH_TO_YOUR_JDK");
e poi ToolProvider.getSystemJavaCompiler();
funziona ma trovo questa soluzione così brutta.
migliori saluti
EDIT: (per dare ulteriori informazioni e riflettono l'ultimo stato) Questa è una rappresentazione di base di web-app-struttura:
myApp
|-conf\...
|-lib\MyJar.jar
|-lib\tools.jar
|-logs\...
|-...
MyJar.jar ha ora un file META-INF/MANIFEST.MF
con il seguente contenuto:
Manifest-Version: 1.0
Sealed: true
Main-Class: here.comes.my.main.class
Class-Path: tools.jar
Senza avvio dell'app Play, sto provando (nella cartella lib
): java -jar MyJar.jar
- il mio semplice metodo main
tenta di richiamare il compilatore (ToolProvider.getSystemJavaCompiler();
) e restituisce null
. Quindi questo mi porta a credere che il problema non ha nulla a che fare con il gioco - Non riesco nemmeno a ottenere un compilatore quando normalmente eseguo il mio Jar!
'JAVA_HOME' è impostato sulla mia macchina di sviluppo, restituendo il percorso al JDK quando richiesto. Ma ottenere la proprietà '" java.home "' dall'esecuzione dell'applicazione Play (con 'System.getProperty (...)') restituisce il percorso di JRE. Quindi forse questo è l'unico problema. Ma non dovrebbe esserci un problema quando ho il 'tools.jar' nel mio classpath. E sono abbastanza sicuro che 'tools.jar' si trova nel mio classpath (controllato durante l'esecuzione dell'app Web) e che il file non sia corrotto. Ho intenzione di provare la roba di classload sopra menzionata. – user2229298
Ho eseguito il gioco su Ubuntu e ho potuto ottenere il compilatore Java da scala senza problemi. Forse c'è qualcosa di sbagliato nella configurazione? –
Appena provato 'JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); \t \t \t System.out.println ("Java compiler:" + javaCompiler); 'dal metodo' onStart' in 'app/Global.java' - con' tools.jar' nel classpath della mia app - anche quello sta tornando 'null' – user2229298