编译java文件
使用Java API来编译Java源代码有非常多方法,目前让我们来看一种最简单的方法,通过JavaCompiler进行编译。
使用ToolProvider.getSystemJavaCompiler
来得到一个JavaCompiler
接口的实例。
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
JavaCompiler
中最核心的方法是run()
。通过这个方法能编译java源代码。
int run(InputStream in, OutputStream out, OutputStream err, String... arguments)
参数分别用来为:
- java编译器提供参数
- 得到Java编译器的输出信息
- 接收编译器的错误信息,
- 一个或多个Java源程式文件
如果run编译成功,返回\(0\)。
如果前3个参数传入的是null
,那么run方法将以标准的输入、输出代替,即System.in
、System.out
和System.err
。如果我们要编译一个test.java
文件,并将使用标准输入输出,run的使用方法如下:
int results = tool.run(null, null, null, "test.java");
完整的例子:
//CompileMain.java
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class CompileMain {
public static void main(String[] args) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null, null, null, "win.hgfdodo.dynamic.test.java");
System.out.println(result == 0 ? "编译成功" : "编译失败");
Process process = Runtime.getRuntime().exec("java win.hgfdodo.dynamic.test");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String str;
while ((str = bufferedReader.readLine()) != null) {
System.out.println(str);
}
}
}
//test.java
public class test {
public static void main(String[] args) {
System.out.println("This is win.hgfdodo.dynamic.test class!");
}
}
$ javac CompileMain.java
$ java CompileMain
编译成功
This is test class!
编译非文件形式源代码
JDK 6 的编译器 API 的另外一个强大之处在于,它可以编译的源文件的形式并不局限于文本文件。JavaCompiler
类依靠文件管理服务可以编译多种形式的源文件。比如直接由内存中的字符串构造的文件,或者是从数据库中取出的文件。这种服务是由 JavaFileManager
类提供的。
在Java SE6中最佳的方法是使用StandardJavaFileManager
类。这个类能非常好地控制输入、输出,并且能通过DiagnosticListener
得到诊断信息,而DiagnosticCollector
类就是listener的实现。新的 JDK 定义了 javax.tools.FileObject
和 javax.tools.JavaFileObject
接口。任何类,只要实现了这个接口,就可以被 JavaFileManager
识别。

使用StandardJavaFileManager
步骤:
- 建立一个
DiagnosticCollector
实例 - 通过
JavaCompiler.getStandardFileManager()
方法得到一个StandardFileManager
对象。 - 使用
StandardFileManager
获取需要编译的源代码。从文件或者字符流中获取源代码。 JavaCompiler.getTask()
生成编译任务抽象。- 通过
CompilationTask.call()
方法编译源代码。 - 关闭
StandardFileManager
。
在使用这种方法调用Java编译时最复杂的方法就是getTask
,下面让我们讨论一下getTask
方法。这个方法有如下所示的6个参数。
getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes,
Iterable<? extends JavaFileObject> compilationUnits)
这些参数大多数都可为null
。他们的含义所下。
out
: 用于输出错误的流,默认是System.err
。fileManager
:标准的文件管理。diagnosticListener
: 编译器的默认行为。options
: 编译器的选项classes
:参和编译的class。compilationUnits
: 待编译的Java文件&#