Java程序动态编译Java源文件
最近接触到公司一个项目,需要将生成的源码动态编译,记录下学习过程。
先贴出官网推荐写法:
JavaCompiler.CompilationTask getTask(Writer out,
JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes,
Iterable<? extends JavaFileObject> compilationUnits)
参数:out
- 用于来自编译器的其他输出的 Writer;如果为 null
,则使用 System.err
fileManager
- 文件管理器;如果为 null
,则使用编译器的标准文件管理器
标准文件管理器有两个用途:
• 自定义编译器如何读写文件的基本构建块
• 在多个编译任务之间共享
diagnosticListener
- 诊断侦听器;如果为 null
,则使用编译器的默认方法报告诊断信息
options
- 编译器选项; null
表示没有选项
classes
- 类名称(用于注释处理), null
表示没有类名称
compilationUnits
- 要编译的编译单元; null
表示没有编译单元
Files[] files1 = ...; // input for first compilation task
Files[] files2 = ...; // input for second compilation task
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//DiagnosticCollector为诊断侦听器,用于将诊断信息收集在一个列表中
//可以不设置,为null时默认使用system.err
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
//自定义编译器读写文件的基本构件块Iterable<? extends JavaFileObject>
compilationUnits1 = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files1));
compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits1).call();Iterable<? extends JavaFileObject>
compilationUnits2 = fileManager.getJavaFileObjects(files2); // use alternative method
// reuse the same file manager to allow caching of jar files
compiler.getTask(null, fileManager, null, null, null, compilationUnits2).call();
for (Diagnostic diagnostic :diagnostics.getDiagnostics())
System.out.format("Error on line %d in %d%n",
diagnostic.getLineNumber()
diagnostic.getSource().toUri());
fileManager.close();
记录下自己的一段代码:
public static void main(String[] args) {
//class文件生成目录
String targetPath="D:\\generate\\target";
//源文件目录
String sourcePath="D:\\generate\\source";
File sourceFile=new File(sourcePath);
List<File> sourceFiles = new ArrayList<File>();
compiler(sourceFile,targetPath,sourceFiles);
boolean result = compilerJavaFile(sourceFiles, targetPath);
System.out.println("compiler finish!" + result);
}
/**
* 递归获取java文件
* @param file 需要编译的文件夹
* @param targetPath 编译后class类文件存放目录
*/
public static void compiler(File file,String targetPath,List<File> sourceFiles) {
File targetDir = new File(targetPath);
if (! targetDir.exists())
{
targetDir.mkdirs();
}
if (file != null && file.exists()){
File[] listFiles = file.listFiles();
if (null == listFiles || listFiles.length == 0) {
return;
}
for (File file2 : listFiles) {
// 判断是否是文件夹
if (file2.isDirectory()) {
compiler(file2,targetPath,sourceFiles);
} else {
if (file2.getName().endsWith(".java")) {
//将源文件目录中的Java文件加入集合中
sourceFiles.add(file2);
}
}
}
}else{
System.out.println("传入格式未知文件");
}
}
/**
* 编译java文件
* @param sourcePath
* @param targerPath
* @return
*/
public static boolean compilerJavaFile(List<File> sourceFile, String targerPath) {
StandardJavaFileManager fileManager = getJavaCompiler().getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFile);
return getJavaCompiler().getTask(null, fileManager, null, options, null, compilationUnits).call();
}