2011-10-14 14 views
7

Ho il seguente requisito strano.Come generare bytecode e salvare in un file .class?

mi viene data:

  1. un elenco di alcuni nomi di metodo.
  2. Nomi e tipi di parametri dei metodi precedenti.
  3. La funzionalità dei metodi precedenti. Questo è il seguente: Per ogni parametro, il metodo lo converte in stringa usando toString e ottiene una matrice di stringhe. A questo array, il metodo applica una funzione foo. La funzione foo prende come input un tipo String [] e produce String. I metodi restituiscono ciò che restituisce foo. Il codice foo viene fornito all'interno di un oggetto Java e deve essere utilizzato come una black-box.

Le informazioni in 1. e 2. possono essere in un file di testo o XML. A tale scopo, possiamo considerarlo disponibile all'interno di un oggetto Java in qualsiasi modo scegliamo.

L'attività è quella di creare un file .class (cioè codice bytecode) che implementa tali metodi e può essere eseguito sulla JVM.

Penso che this assembler library sarebbe un modo per farlo. Qualcuno può suggerire un modo più semplice?

[EDIT:] Posso pensare in un altro modo: prima generare il file .java e quindi compilarlo per ottenere il file .class.

[Il contesto:] Devo farlo per diverse centinaia di metodi. Voglio il collegamento in modo da poter automatizzare il mio lavoro piuttosto che scrivere manualmente il codice.

+0

Potrebbe per favore dare più contesto, cosa vuoi ottenere ... L'unica ragione per cui vedo "fare" metodi specifici per un comportamento generico (foo) è la sicurezza del tipo che è utile in fase di compilazione ...Come hai intenzione di usare/chiamare il codice generato? – pgras

+0

Non chiamerò il codice generato. Quello che voglio fare è creare una libreria API (jar) che qualcuno possa usare. La classe avrà un nome specifico, quindi sapranno quale API chiamare. – Jus12

+0

OK Vedo il problema con centinaia di metodi, l'elenco dei metodi cambierà spesso o no? possiamo avere un esempio di input che stai utilizzando? – pgras

risposta

7

È possibile generare il codice del programma richiesto nella sintassi Java e trasformarlo in un file di classe utilizzando il compilatore. È possibile istanziare javac in fase di esecuzione e passargli una matrice di byte anziché la posizione del file di origine. Questo è probabilmente il più semplice da mantenere per gli altri programmatori.

Se si desidera generare direttamente il codice byte, asm è la libreria più comunemente utilizzata.

+0

Penso che questo sia probabilmente il modo più conveniente (generare il file '.java'). – Jus12

+0

Puoi dare qualche informazione su come farlo tramite 'javac' assumendo che io abbia creato il file .java? – Jus12

+1

È nel pacchetto 'javax.tools'. Questo articolo ha un esempio: http://www.ibm.com/developerworks/java/library/j-jcomp/index.html. Devo ammettere che non ho usato l'API 'javax.tools' da solo. – Barend

1

ho visto si risponde al mio commento, ma non è ancora chiaro per me il motivo per cui si desidera generare il codice per essere poi confezionato in un barattolo, basta digitare :)

Ora, se si desidera un typesafe api con tutti i metodi che hanno lo stesso comportamento potresti fornire un proxy dinamico per una determinata interfaccia (questo ti lascia con la domanda su come generare l'interfaccia :)

Ecco un esempio in cui tutte le chiamate a tutto il metodo MyInterface sarà gestito dal metodo invoke (basta aggiungere metodi all'interfaccia per testarlo) ...

package test; 

import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 

public class Test { 

interface MyInterface { 

    String methodOne(String s); 

    String methodTwo(String s, Integer i); 
} 

static MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
     MyInterface.class.getClassLoader(), 
     new Class[] { MyInterface.class }, new InvocationHandler() { 
      public Object invoke(Object proxy, Method method, Object[] args) 
        throws Throwable { 
       StringBuilder result = new StringBuilder(); 
       for (Object arg : args) { 
        result.append(arg.toString()); 
       } 
       return result.toString(); 
      } 
     }); 

public static void main(String[] args) { 
    System.out.println(proxy.methodOne("hello"));  
    System.out.println(proxy.methodTwo("world", 5)); 

} 

} 
+0

Se potessi digitare così tanto, non sarebbe stato necessario fare la domanda :-). Uso Scala principalmente perché non mi piace scrivere. – Jus12

Problemi correlati