2009-04-23 10 views
17

In Java, è possibile creare una definizione di classe al volo mentre un'applicazione è in esecuzione e quindi creare un oggetto di quella classe?Definizione di una classe mentre è in esecuzione un'applicazione Java

Ad esempio, un'applicazione in esecuzione leggere in un file di testo che contiene un elenco di membri della classe da includere nella nuova classe. L'applicazione definirà quindi una definizione di classe basata sull'elenco di membri e quindi la renderà insana.

+25

Ecco come viene avviato SkyNet. – TheTXI

+7

Se SkyNet fosse scritto in Java, richiederebbe troppa memoria per essere mai una minaccia. – Pesto

+4

SkyNet si costruirà solo un cluster più grande per l'esecuzione. Il fatto che sia scritto in Java avrebbe senso dal momento che SkyNet e Java finiranno per essere la fine dell'umanità. – TheTXI

risposta

11

Sì, è possibile farlo in teoria il file di classe è il byte code che è alla fine un array di byte! è quindi possibile utilizzare il metodo defineClass (String, byte [], int, int) per ottenere un'istanza di classe che può essere utilizzata per creare un'istanza degli oggetti tramite la reflection.

In pratica è possibile utilizzare qualcosa come CGLib o javaassist.

È anche possibile utilizzare la lunga modalità di generazione del codice java in un file, richiamando il compilatore e quindi caricando il file.

1

È possibile eseguire questa operazione scrivendo il codice per la nuova classe in un file, quindi richiamando il compilatore Java su quel file e utilizzando un classloader per caricare dinamicamente tale classe nell'applicazione in esecuzione. Apache Tomcat fa questo per le sue pagine JSP; prende il codice, apporta alcune modifiche ad esso, lo avvolge in un blocco try/catch nel mezzo di una classe, che poi scrive nel filesystem, lo compila e usa un classloader per ottenere e citare in giudizio per servire le richieste.

2

È possibile generare dinamicamente le classi utilizzando ASM

0

Forse un po 'eccessivo, il Apache BCEL (codice Byte Engineering Library) può essere utilizzato per creare class file durante il runtime.

Anche se non l'ho ancora provato, è possibile creare una classe, caricarla e creare un'istanza durante il runtime.

0

Sì, è possibile.

È possibile creare classi con Javassist in fase di esecuzione definendo il corpo della classe e rendendo javassist compilare la nuova classe.

Javassist ha un compilatore personalizzato che crea un bytecode basato sulla definizione della classe. Ha alcuni modi particolari per gestire le cose, ma è molto semplice e intuitivo usare questa libreria.

Javassist viene utilizzato su JBoss, e penso che sia un buon riferimento :)

Lo stesso può essere realizzato con BCEL, ma è molto più difficile (ma in questo modo si ha più il controllo su ciò che viene generato).

0

Probabilmente potresti fare qualcosa del genere con JRuby, o JPython o Groovy se devi.

Se ti senti particolarmente masochista puoi guardare BCEL.

0

Se si desidera Java e metrogrammazione, utilizzare Groovy.

+0

Ciao Stefan, quindi Groovy può aiutare a compilare in runtime una classe Java al volo e istanziarla? Avete qualche puntatore su come fare questo? – Sergio

0

ASM è la libreria bytecode di livello più basso per Java, suppongo. Ciò lo rende molto difficile ma anche molto potente.Raccomando di leggere la documentazione di ASM (PDF) per capire veramente come funziona la generazione di bytecode in Java. Questa documentazione spiega anche come caricare il bytecode nel caricatore di classi (un altro argomento difficile da fare correttamente).

Dopodiché puoi usare una delle librerie di livello superiore, se ti semplifica la vita e capire cosa fanno. Per molti casi, come la generazione di proxy, lo CGLIB è utile e semplice da usare. Per più potenza, molti hanno menzionato Javassist (non l'ho usato - CGLIB e ASM sono stati buoni per me).

1

Forse la più semplice soluzione di (in termini di non richiedere librerie extra) potrebbe essere quella di utilizzare il Java compiler API che viene fornito con Java 6. Basta solo essere in grado di generare il java, compilare e quindi eseguire un Class.forName().

+0

che funzionerebbe solo se il jdk è installato, giusto? – Sergio

0

C'è stata una domanda recente in merito allo in-memory compilation che dovrebbe darvi alcuni suggerimenti su cosa fare dopo che siete riusciti a generare il codice sorgente.