动态编译,无需创建物理文件



我按照通过Java编译器API动态生成Java类的教程进行操作,代码是有效的,但我看到的是程序将在编译后创建一个类文件。

import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.*;
public class Compiler {
    static final Logger logger = Logger.getLogger(Compiler.class.getName());
    static String sourceCode = "class HelloWorld{"
        + "public static void main (String args[]){"
        + "System.out.println ("Hello, dynamic compilation world!");"
        + "}"
        + "}";
    public void doCompilation() {
        SimpleJavaFileObject fileObject = new DynamicJavaSourceCodeObject("HelloWorld", sourceCode);
        JavaFileObject javaFileObjects[] = new JavaFileObject[]{fileObject};
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, Locale.getDefault(), null);
        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(javaFileObjects);
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
        CompilationTask compilerTask = compiler.getTask(null, stdFileManager, diagnostics, null, null, compilationUnits);
        boolean status = compilerTask.call();
        if (!status) {
            for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
                System.out.format("Error on line %d in %sn", diagnostic.getLineNumber(), diagnostic);
            }
        }
        try {
            stdFileManager.close();
        } catch (IOException ex) {
            Logger.getLogger(Compiler.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    public static void main(String args[]) {
        new Compiler().doCompilation();
    }
}
class DynamicJavaSourceCodeObject extends SimpleJavaFileObject {
    private String qualifiedName;
    private String sourceCode;
    protected DynamicJavaSourceCodeObject(String name, String code) {
        super(URI.create("string:///" + name.replaceAll("\.", "/") + JavaFileObject.Kind.SOURCE.extension), JavaFileObject.Kind.SOURCE);
        this.qualifiedName = name;
        this.sourceCode = code;
    }
    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors)
        throws IOException {
        return sourceCode;
    }
    public String getQualifiedName() {
        return qualifiedName;
    }
    public void setQualifiedName(String qualifiedName) {
        this.qualifiedName = qualifiedName;
    }
    public String getSourceCode() {
        return sourceCode;
    }
    public void setSourceCode(String sourceCode) {
        this.sourceCode = sourceCode;
    }
}

调用compilerTask.call();后是否有可能不创建类文件?如果是,该怎么做?

对于你的所作所为,我会使用 Janino。 它似乎只使用JavaCompiler是可行的,但没有很好的记录。 请参阅我添加的链接问题注释,以获取使用 JavaCompiler 的示例。

编辑:我使用JavaCompiler找到了一个易于理解的示例。

要避免 JavaCompiler 创建类文件,请使用参数:"-proc:only"

最新更新