2010-12-16 8 views
8

¿Hay alguna manera de que un programa Java en ejecución compile el código fuente de Java (pasado como una cadena)?¿Compila el código fuente de Java a partir de una cadena?

Class newClass = Compiler.compile ("class ABC { void xyz {etc. etc. } }"); 

Idealmente, cualquier clase que hace referencia el código fuente aprobada en serían resueltas por el cargador de clases del programa.

¿Algo como esto existe?

+0

me encontré con este ejemplo, que es exactamente lo que necesito. http://www.ibm.com/developerworks/java/library/j-jcomp/index.html – user566822

Respuesta

9

Sure. Eche un vistazo a la clase JavaCompiler y las otras clases en el paquete javax.tools.

Han existido desde Java 1.6.

Here is some example code.

(Como ha señalado @Sergey Tachenov en los comentarios, sino que precisa de JDK para ser instalado como el archivo tools.jar necesaria viene con el JDK pero no JRE.)

+4

Creo que vale la pena señalar que no funciona solo con JRE de Sun, necesita que se instale JDK como necesario El archivo tools.jar viene con JDK pero no con JRE. –

+0

Probé este ejemplo, estoy teniendo una 'java.lang.ClassNotFoundException: Test' en' Class clazz = Class.forName ("Test"); '! – bachr

+0

¿El directorio de salida de la compilación está en la ruta de clase? – aioobe

3

depende de lo que quiero hacer. Si solo quieres ejecutar un código, puedes usar BeanShell. No es una clase compilada en java, pero es muy útil para hacer algo flexible

1

Puede probar mi biblioteca de esencia jcf que hace esto. Cuando se ejecuta en depuración, puede escribir la fuente en un archivo para que pueda ingresar al código. De lo contrario, hace todo en la memoria. Envuelve el JavaCompiler en tools.jar

Toma una cadena, la compila y la carga en el cargador de clases actual y devuelve la clase. Maneja clases anidadas/internas.

http://vanillajava.blogspot.com/2010/11/more-uses-for-dynamic-code-in-java.html

Nota: No he conseguido esta trabajando en OSGi. ;)

1

Javassist puede generar y cargar en tiempo de ejecución las clases y métodos de Cadenas de código fuente. También es posible volcar en el sistema de archivos la clase generada si es necesario.

Actualmente, hay pequeñas limitaciones en el código que puede pasar en esas cadenas, por ejemplo, no puede incluir genéricos, enumeraciones o autoboxing y inboxing de primitivas. Más información aquí:

http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/

4

Lo que necesita es una clase que se extiende JavaFileObject

import java.net.URI; 

import javax.tools.SimpleJavaFileObject; 

public class JavaSourceFromString extends SimpleJavaFileObject { 
    final String code; 

    public JavaSourceFromString(String name, String code) { 
     super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE); 
     this.code = code; 
    } 

    @Override 
    public CharSequence getCharContent(boolean ignoreEncodingErrors) { 
     return code; 
    } 
} 

que puede ser utilizado de la siguiente manera:

JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); 
if(jc == null) throw new Exception("Compiler unavailable"); 

String code = "public class CustomProcessor { /*custom stuff*/ }"; 
JavaSourceFromString jsfs = new JavaSourceFromString("CustomProcessor", code); 

Iterable<? extends JavaFileObject> fileObjects = Arrays.asList(jsfs); 

List<String> options = new ArrayList<String>(); 
options.add("-d"); 
options.add(compilationPath); 
options.add("-classpath"); 
URLClassLoader urlClassLoader = (URLClassLoader)Thread.currentThread().getContextClassLoader(); 
StringBuilder sb = new StringBuilder(); 
for (URL url : urlClassLoader.getURLs()) { 
    sb.append(url.getFile()).append(File.pathSeparator); 
} 
sb.append(compilationPath); 
options.add(sb.toString()); 

StringWriter output = new StringWriter(); 
boolean success = jc.getTask(output, null, null, options, null, fileObjects).call(); 
if(success) { 
    logger.info(LOG_PREFIX + "Class has been successfully compiled"); 
} else { 
    throw new Exception("Compilation failed :" + output); 
} 
+0

¿dónde declaraste la variable 'compilationPath'? – bachr

+0

Está más arriba en el código, solo una cadena realmente – MonoThreaded

Cuestiones relacionadas