2010-12-16 146 views
8

有没有一种运行Java程序来编译Java源代码(以字符串形式传递)的方法?从字符串编译Java源代码?

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

理想情况下,传入的源代码所引用的任何类都将被程序的类加载器解析。

是否有这样的事情存在?

+0

我发现这个例子中,这正是我需要的。 http://www.ibm.com/developerworks/java/library/j-jcomp/index.html – user566822 2012-10-24 23:48:18

回答

9

当然。查看JavaCompiler类和javax.tools包中的其他类。

自Java 1.6以来,它们一直存在。

Here is some example code.

(正如在评论中指出的@Sergey Tachenov,它需要JDK安装为必要的tools.jar文件带有JDK而不是JRE)

+4

我认为值得注意的是,它仅适用于Sun的JRE,它需要根据需要安装JDK tools.jar文件附带JDK,但不附带JRE。 – 2010-12-16 17:34:34

+0

我试过这个例子,我在'Class clazz = Class.forName(“Test”)上有'java.lang.ClassNotFoundException:Test';'! – bachr 2014-01-21 10:17:04

+0

是类路径上编译的输出目录吗? – aioobe 2014-01-21 12:02:55

3

取决于你想做。 如果你只是想运行一些代码,你可以使用BeanShell。这不是一个Java编译类,但是非常有用,使灵活的东西

1

你可以尝试我的本质jcf库这样做。在调试中运行时,可以将源代码写入文件,以便您可以进入代码。否则,它会在内存中执行所有操作。它将JavaCompiler包装在tools.jar中

它接受一个字符串,编译并将其加载到当前类加载器中并返回该类。它处理嵌套/内部类。

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

注:我还没有在OSGi的这个工作。 ;)

1

Javassist可以在运行时从源代码的字符串生成和加载类和方法。 如果需要,也可以在文件系统中转储生成的类。

当前,您可以在这些字符串中传递的代码存在较小的限制,例如,它不能包含泛型,枚举或自动装箱和收件箱原语。 点击此处了解详情:

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

4

你需要的是一个扩展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; 
    } 
} 

这可以如下的一类:

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

你在哪里声明了'compilationPath'变量? – bachr 2014-01-21 09:48:23

+0

它在代码中更高,只是一个字符串 – MonoThreaded 2014-01-24 14:36:25