Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it
    Registrato dal
    Jul 2014
    Messaggi
    5

    [JAVA] Compilare una classe a Runtime da file .java scritto con FileWriter

    Salve,
    Vi espongo la mia questione.
    Quello che vorrei fare è come da titolo, compilare un file sorgente .java a runtime generando così la classe.
    Questo file non è già presente nel package al momento del lancio dell'applicativo, ma viene generato qualora l'utente ne manifestasse l'intenzione tramite il FileWriter.
    Effettivamente il programma genera il file con estensione .java qualora lo volessi fare, e lo salva nella corretta sottodirectory di src. Tuttavia se voglio istanziare mediante reflection un oggetto di questa nuova classe, ovviamente mi da ClassNotFoundException dicendomi che non è presente la classe poichè non è stata compilata (correggetemi se sbaglio, sono uno studente e non un programmatore esperto ) e quindi non è presente nella corrispettiva sottodirectory in bin (dove ci sono i bytecode dei file sorgente compilati). Se volessi compilare questa nuova classe che ho scritto, per andare a inserire nel bin il bytecode compilato e poter dunque istanziare la nuova classe scritta in runtime con FileWriter cosa devo fare? Sto provando a impazzire con javassist ma non ce ne levo le gambe...
    Grazie a tutti per l'aiuto in anticipo

  2. #2
    Utente di HTML.it L'avatar di Nikopol
    Registrato dal
    Jan 2011
    Messaggi
    120
    Ciao,
    un modo per farlo sarebbe fare realizzare alla classe da compilare un interfaccia che dichiara tutti i metodi da usare.
    Es(con un solo metodo):
    codice:
    package compilazionedemo;
    
    public interface IPippo {
        void saluta();
    }
    e il file.java da compilare:
    codice:
    import compilazionedemo.IPippo;
    public class Prova implements IPippo{
        public void saluta() {
            System.out.println("Hello World!");
        }
    }
    Da notare che la classe non farà parte dei package del tuo programa, quindi non devi specificare il package e devi fare l'import di tutte le classi/interfacce che userai.

    Adesso puoi compilare la classe in questo modo ed ottenere un riferimento all'oggetto istanziato di tipo interfaccia IPippo:
    codice:
    package compilazionedemo;
    
    import java.io.File;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.Arrays;
    import javax.tools.JavaCompiler;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    
    public class CompilatoreDemo {
        public IPippo compile(String fileAbsolutePath) throws MalformedURLException, 
                ClassNotFoundException, InstantiationException, IllegalAccessException{
            //Il compilatore
            JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
    
            //Il gestore dei file da compilare
            StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null);
            
            //Il file da compilare
            File javaFile = new File(fileAbsolutePath);
    
            //Una collezione di file da compilare; nel nostro caso solo uno
            Iterable fileObjects = sjfm.getJavaFileObjects(javaFile);
    
            //Cartella dove inserire il file compilato ovvero la cartella /bin
            String dir=System.getProperty("user.dir");
           
            String[] options = new String[]{"-d", dir};
            //Esegue la compilazione
            jc.getTask(null, null, null, Arrays.asList(options), null, fileObjects).call();
    
            //Costruzione dell'url della cartella dove è presente il file compilato
            URL[] urls = new URL[]{ new URL("file://"+dir+File.separator) };
    
            //Creazione del caricatore della classe compilata
           URLClassLoader ucl = new URLClassLoader(urls);
            
            //Costruzione nome classe
            String className=fileAbsolutePath.substring(
                    fileAbsolutePath.lastIndexOf(File.separator)+1,
                    fileAbsolutePath.indexOf("."));
    
            //caricamento classe
            Class clazz = ucl.loadClass(className);
            
            //Creazione oggetto
            return (IPippo) clazz.newInstance();
            
        }
    }
    e per testarlo:
    codice:
    package compilazionedemo;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.MalformedURLException;
    
    public class Main {
    
        public static void main(String[] args) throws IOException,MalformedURLException,ClassNotFoundException,
                        InstantiationException,  IllegalAccessException {
         
            File f = new File ("Prova.java");
            CompilatoreDemo cd = new CompilatoreDemo();
            IPippo unPippo = cd.compile(f.getAbsolutePath());
            unPippo.saluta();
        }
    }
    Sono uno studente anch'io e ho preso spunto da un progettino che avevo fatto alle superiori un paio di anni fa e da allora non ho più approfondito l'argomento; probabilmente ci sono modi migliori per farlo ma spero che possa almeno aiutarti ad inquadrare il problema.
    Ultima modifica di Nikopol; 19-07-2014 a 02:34 Motivo: errore di battitura

  3. #3
    Utente di HTML.it
    Registrato dal
    Jul 2014
    Messaggi
    5
    Ciao!
    Ti ringrazio per l'aiuto, gentilissimo.
    Comunque questo codice mi da un eccezione NullPointerException quando faccio
    StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null);

  4. #4
    Utente di HTML.it L'avatar di Nikopol
    Registrato dal
    Jan 2011
    Messaggi
    120
    strano, a me funziona alla perfezione.
    Se ToolProvider.getSystemJavaCompiler() restituisce null significa che non riesce a trovare il compilatore del jdk.
    Hai settato le variabili d'ambiente correttamente?
    La Guida Galattica è infallibile.
    È la realtà, spesso, ad essere inesatta.

  5. #5
    Utente di HTML.it
    Registrato dal
    Jul 2014
    Messaggi
    5
    Ah si giusto, le modificai per usare mingw grazie !

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.