2011-10-14 18 views
7

Tengo el siguiente requisito raro.¿Cómo se genera bytecode y se guarda en el archivo .class?

se me da:

  1. una lista de algunos nombres de los métodos.
  2. Nombres y tipos de parámetros de los métodos anteriores.
  3. La funcionalidad de los métodos anteriores. Esto es como sigue: Para cada parámetro, el método lo convierte en cadena usando toString y obtiene una matriz de cadenas. Para esta matriz, el método aplica una función foo. La función foo toma como entrada un tipo String [] y produce String. Los métodos devuelven lo que foo devuelve. foo El código se da dentro de un objeto Java y se debe acceder como un recuadro negro.

La información en 1. y 2. puede estar en un archivo de texto o XML. Para este propósito, podemos considerar que está disponible dentro de un objeto Java de la manera que elijamos.

La tarea es crear un archivo .class (es decir, bytecode) que implemente esos métodos y se pueda ejecutar en la JVM.

Creo que this assembler library sería una forma de hacerlo. ¿Alguien puede sugerir una manera más fácil?

[EDIT:] Puedo pensar de otra manera: primero genere el archivo .java y luego compílelo para obtener el archivo .class.

[El contexto:] Tengo que hacer esto por varios cientos de métodos. Quiero el atajo para poder automatizar mi trabajo en lugar de escribir el código manualmente.

+0

Podría por favor dar más contexto, ¿qué quiere lograr ... La única razón que veo para "hacer" métodos específicos para un comportamiento genérico (foo) es seguridad tipo que es útil en tiempo de compilación ...¿Cómo vas a usar/invocar el código generado? – pgras

+0

No llamaré al código generado. Lo que quiero hacer es crear una biblioteca API (jar) para que alguien la use. La clase tendrá un nombre específico, por lo que sabrán a qué API llamar. – Jus12

+0

OK Veo el problema con cientos de métodos, ¿la lista de métodos cambiará a menudo o no? ¿Podemos tener un ejemplo de la entrada que estás usando? – pgras

Respuesta

7

Puede generar el código de programa requerido en la sintaxis de Java y convertirlo en un archivo de clase utilizando el compilador. Es posible instanciar javac en tiempo de ejecución y pasarlo a una matriz de bytes en lugar de a la ubicación del archivo fuente. Esto es probablemente el más fácil de mantener para otros programadores.

Si desea generar código de bytes directamente, asm es la biblioteca más utilizada.

+0

Creo que esta sería probablemente la forma más conveniente (generando el archivo '.java'). – Jus12

+0

¿Puedes darnos alguna información sobre cómo hacer esto a través de 'javac' suponiendo que he creado el archivo .java? – Jus12

+1

Está en el paquete 'javax.tools'. Este artículo tiene un ejemplo: http://www.ibm.com/developerworks/java/library/j-jcomp/index.html. Debo admitir que no he usado la API 'javax.tools'. – Barend

1

vi su respuesta a mi comentario, pero todavía no está claro para mí por qué quiere generar el código para luego ser envasada en un frasco, sólo tiene que escribir él :)

Ahora bien, si quieres un typesafe Api con todos los métodos que tienen el mismo comportamiento que usted podría proporcionar un proxy dinámico para una interfaz determinada (esto le deja con la pregunta sobre cómo generar la interfaz :)

Aquí hay un ejemplo donde todas las llamadas a todo el método MyInterface será manejado por el método de invocación (simplemente agregue métodos a la interfaz para probarlo) ...

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

Si pudiera escribir tanto, no habría habido necesidad de hacer la pregunta :-). Uso Scala principalmente porque no me gusta escribir. – Jus12

Cuestiones relacionadas