compiler java compiler-construction runtime compilation runtime-compilation

java - jit compiler



Compilación de código java sobre la marcha para Java 5 y Java 6 en la memoria (6)

¿Cómo puedo compilar código java desde una cadena arbitraria (en memoria) en Java 5 y Java 6, cargarlo y ejecutar un método específico en él (predefinido)?

Antes de encender esto, miré las implementaciones existentes:

  • La mayoría confía en Java 6 Compiler API.
  • Los que no lo hacen, confían en los trucos.
  • Sí, eché un vistazo a commons-jci. O soy demasiado denso para entender cómo funciona, o simplemente no funciona.
  • No pude encontrar cómo alimentar al compilador mi ruta de clase actual (que es bastante enorme).
  • En la implementación que funcionó (en Java 6), no pude encontrar cómo cargar correctamente las clases internas (o las clases anónimas internas).
  • Me gustaría bastante si todo estuviera en memoria, ya que se ejecuta en múltiples entornos.

Estoy seguro de que esto se ha resuelto anteriormente, pero no puedo encontrar nada que parezca siquiera una calidad de media producción en google (excepto jci, que, como he dicho antes, no he logrado usar).

Editar:

  • Miré sobre JavaAssist: necesito clases internas, soporte de nivel de lenguaje Java 5.0 y compilación con todo el classpath. Además, me gustaría crear nuevas clases sobre la marcha. Podría estar equivocado, pero no pude encontrar cómo hacer esto con JavaAssit.
  • Estoy dispuesto a usar una solución basada en sistema de archivos (llamada javac) pero no sé cómo adivinar el classpath, ni cómo cargar los archivos más adelante (que no están en mi classpath) con un cargador de clases especial que puede ser Reciclado para múltiples invocaciones. Si bien sé cómo investigarlo, preferiría una solución lista.

Edit2: Por el momento, estoy contento con BeanShell "evaluar". Aparentemente hace todo lo que necesito para (obtener una cadena, evaluarla en el contexto de la ruta de clase "actual". Extraña algunas de las características de Java 5, pero puede usar enumeraciones (no definir) y compiladas "genéricas" (borradas ) Clases, por lo que debería ser suficiente para lo que quiero.

No quiero marcar la respuesta como aceptada todavía, ya que espero que surja una mejor solución.

Edit3: aceptó la sugerencia de la cáscara de frijol - realmente funciona maravillosamente.


Ejecutar dentro de un contenedor web como Tomcat y primero generar una página JSP, y luego invocarlo.

Esto también le permite deshacerse de las definiciones de clase antiguas simplemente sobrescribiendo la página JSP en lugar de hacer que su cargador de clases se ejecute lentamente.

¿El requisito "en memoria" se debe a la velocidad o al no cambiar el código base?


Es posible que desee revisar a Janino también.

Desde su página web:

Janino es un compilador que lee una expresión JavaTM, un bloque, un cuerpo de clase, un archivo fuente o un conjunto de archivos fuente, y genera un bytecode JavaTM que se carga y ejecuta directamente. Janino no pretende ser una herramienta de desarrollo, sino un compilador incorporado para propósitos de compilación en tiempo de ejecución, por ejemplo, evaluadores de expresiones o motores de "páginas de servidor" como JSP.

http://www.janino.net/

Actualmente lo estoy usando en un proyecto de misión crítica bastante grande y funciona bien


JCI se ve bien. Este fragmento de código debe ser su base:

JavaCompiler compiler = new JavaCompilerFactory().createCompiler("eclipse"); MemoryResourceReader mrr = new MemoryResourceReader(); mrr.add("resource name string", yourJavaSourceString.getBytes()); MemoryResourceStore mrs = new MemoryResourceStore(); CompilationResult result = compiler.compile(sources, mrr, mrs); // don''t need the result, unless you care for errors/warnings // the class should have been compiled to your destination dir

¿Alguna razón por la que esto no debería funcionar?

Editar: agregó un MemoryResourceStore para enviar a la memoria la salida de la clase compilada, como se solicitó.

Además, la configuración de javac , como classpath en su caso, se puede hacer a través de setCustomArguments(String[] pCustomArguments) en la clase JavacJavaCompilerSettings .


Si no está completamente vinculado a la compilación, las soluciones como Beanshell, groovy y los otros lenguajes de scripting se integran fácilmente (de hecho, Java tiene soporte incorporado para conectar un lenguaje de scripting, por lo que su código ni siquiera sabe qué idioma) el guion esta escrito en

Beanshell debería ejecutar cualquier código 100% java IIRC, y creo que Groovy puede ejecutar la mayoría de los códigos java, posiblemente todos.


ECJ Eclipse Java Compiler

Eclipse proporciona y utiliza su propio compilador que no es javac

  • El compilador de Eclipse se usa dentro del IDE (Eclipse)
  • El compilador Eclipse también se puede utilizar como un compilador de lotes puros fuera de Eclipse

Compilar un archivo fuente

$ java -jar ecj-3.5.2.jar HelloWorld.java