最近接觸到公司一個項目,需要將生成的源碼動態編譯,記錄下學習過程。
先貼出官網推薦寫法:
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();
}