2010-12-16 5 views
8

Existe-t-il un moyen pour un programme Java en cours de compiler du code source Java (transmis en tant que chaîne)? Idéalement, toutes les classes référencées par le code source transmis seraient résolues par le chargeur de classe du programme.Compiler le code source Java à partir d'une chaîne?

Est-ce que quelque chose comme ça existe?

+0

Je trouve cet exemple, qui exactement Ce dont j'ai besoin. http://www.ibm.com/developerworks/java/library/j-jcomp/index.html – user566822

Répondre

9

Bien sûr. Jetez un oeil à la classe JavaCompiler et les autres classes dans le package javax.tools.

Ils existent depuis Java 1.6.

Here is some example code.

(Comme l'a souligné @Sergey Tachenov dans les commentaires, il faut être installé JDK que le fichier tools.jar nécessaire est livré avec JDK mais pas JRE.)

+4

Je pense qu'il vaut la peine de noter que cela ne fonctionne pas avec JRE de Sun seulement, il faut que JDK soit installé comme nécessaire Le fichier tools.jar est fourni avec JDK mais pas JRE. –

+0

J'ai essayé cet exemple, j'ai une 'java.lang.ClassNotFoundException: Test' sur' Class clazz = Class.forName ("Test"); '! – bachr

+0

Le répertoire de sortie de la compilation est-il sur le chemin de la classe? – aioobe

3

dépend de ce que vouloir faire. Si vous voulez juste exécuter du code, vous pouvez utiliser BeanShell. Ce n'est pas une classe java compilée, mais elle est très utile pour faire quelque chose de flexible

1

Vous pouvez essayer ma bibliothèque essence jcf qui fait cela. Lors de l'exécution du débogage, vous pouvez écrire la source dans un fichier afin de pouvoir entrer dans le code. Sinon, il fait tout en mémoire. Il enveloppe le JavaCompiler dans tools.jar

Il prend une chaîne, la compile et la charge dans le chargeur de classe actuel et renvoie la classe. Il gère les classes imbriquées/internes.

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

Note: Je n'ai pas ce travail dans OSGi. ;)

1

Javassist peut générer et charger des classes et des méthodes d'exécution à partir de chaînes de code source. Il est également possible de vider dans le système de fichiers la classe générée si nécessaire.

Actuellement, il existe des limitations mineures dans le code que vous pouvez transmettre dans ces chaînes, par exemple, il ne peut pas inclure de génériques, d'énumérations ou d'envoi automatique de primitives. Plus d'informations ici:

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

4

Qu'est-ce que vous avez besoin est une classe qui étend 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; 
    } 
} 

qui peut être utilisé comme suit:

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

où avez-vous déclaré la variable 'compilationPath'? – bachr

+0

Il plus haut dans le code, juste une chaîne vraiment – MonoThreaded

Questions connexes