Pregunta

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

Antes de hacer esto, miré las implementaciones existentes:

  • La mayoría depende de la API del compilador de Java 6.
  • Los que no lo hacen, confían en los trucos.
  • Sí, revisé 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 la forma correcta de cargar clases internas (o 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 resolvió anteriormente, pero no puedo encontrar nada que parezca ni siquiera la calidad de media producción en google (excepto jci, que, como he dicho antes, no he logrado usar) .

Editar:

  • Busqué en JavaAssist: necesito clases internas, compatibilidad con el nivel de lenguaje Java 5.0 y compilación con toda la ruta de clase. Además, me gustaría crear nuevas clases sobre la marcha. yo 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 (que llama a 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 ahora, estoy contento con BeanShell " evalúe " ;. 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 funciones 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 beanshell, realmente funciona de maravilla.

¿Fue útil?

Solución

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 saber en qué idioma está escrito el script)

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.

Otros consejos

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 la salida de la clase compilada a la memoria, como solicitó.

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

Javassist puede interesarte

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

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.

Es el " en memoria " ¿Requisito debido a la velocidad o por no cambiar el código base?

Compilador Java ECJ Eclipse

Eclipse proporciona y utiliza su propio compilador que no es javac

  • El compilador 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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top