从字符串编译Java源代码?

时间:2010-12-16 17:09:12

标签: java compiler-construction

有没有办法让正在运行的Java程序编译Java源代码(以字符串形式传递)?

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

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

这样的事情是否存在?

5 个答案:

答案 0 :(得分:9)

不确定。查看JavaCompiler类以及javax.tools包中的其他类。

他们自Java 1.6以来一直存在。

Here is some example code.

(正如@Sergey Tachenov在评论中指出的那样,它需要安装JDK作为必要的tools.jar文件随JDK一起提供而不是JRE。)

答案 1 :(得分: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);
}

答案 2 :(得分:3)

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

答案 3 :(得分:1)

你可以试试我的精华jcf库来做到这一点。在调试中运行时,可以将源写入文件,以便您可以单步执行代码。否则,它会在内存中完成所有操作。它将JavaCompiler包装在tools.jar

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

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

注意:我没有在OSGi中使用它。 ;)

答案 4 :(得分:1)

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

目前,您可以在这些字符串中传递的代码存在一些小的限制,例如,它不能包含泛型,枚举或自动装箱以及基元的收件箱。 更多信息:

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