从1.6版本的JDK开始,JDK提供了标准的包(javax.tools)可以方便的调用JVM的编译器,可以方便的通过JVM的编译器来编译java源文件。
JDK提供的调用接口是JavaCompiler类,该类及CompilerAPI相关类在JDK的tools.jar包中。
注意:在开发过程中由于使用的开发工具(IntelliJ IDEA或Eclipse)默认加载jdk包中的jre下的lib中的jar,请检查是否将lib下的tool.jar引入,
如果没有引用将导致ClassNotFoundException异常
编译java文件demo
public boolean compiler(String encoding, String filePath,String outputFile, DiagnosticCollector<JavaFileObject> diagnostics) throws Exception{
String sourceDir=filePath;
String targetDir="";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, Charset.forName(encoding));
try {
List<File> jars = new ArrayList<File>();
getJarFiles(new File(filePath),jars);
File sourceFile = new File(sourceDir);
List<File> sourceFileList = new ArrayList<File>();
getSourceFiles(sourceFile, sourceFileList);
if (sourceFileList.size() == 0) {
System.out.println(sourceDir + "目录下查找不到任何java文件");
return false;
}
List<File> dependencies = new ArrayList<File>();
dependencies.addAll(jars);
fileManager.setLocation(StandardLocation.CLASS_PATH,dependencies);
fileManager.setLocation(StandardLocation.SOURCE_PATH,sourceFileList);
fileManager.setLocation(StandardLocation.CLASS_OUTPUT,Arrays.asList(new File[]{new File(outputFile)}));
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
Iterable<String> options = Arrays.asList("-encoding", encoding,"-source","1.8");
JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
return compilationTask.call();
}finally {
fileManager.close();
}
}
查找该目录下的所有的java文件
private void getSourceFiles(File sourceFile, List<File> sourceFileList) throws Exception {
if (sourceFile.exists() && sourceFileList != null) {
if (sourceFile.isDirectory()) {
File[] childrenFiles=sourceFile.listFiles((pathname->{
if (pathname.isDirectory()) {
return true;
}else{
String name = pathname.getName();
if (name.endsWith(".java") ? true : false) {
return true;
}
return false;
}
}));
for (File childFile : childrenFiles) {
getSourceFiles(childFile, sourceFileList);
}
}else{
String name = sourceFile.getName();
if (name.endsWith(".java") ? true : false) {
sourceFileList.add(sourceFile);
}
}
}
}
递归查找该目录下的所有的jar文件
private void getJarFiles(File jarFile,List<File> jars) throws Exception {
if (jarFile.exists() && jarFile != null) {
if (jarFile.isDirectory()) {
File[] childrenFiles= jarFile.listFiles((pathname) -> {
if (pathname.isDirectory()) {
return true;
} else {
String name = pathname.getName();
if (name.endsWith(".jar") ? true : false) {
return true;
}
return false;
}
});
for (File childFile : childrenFiles) {
getJarFiles(childFile, jars);
}
}else{
String name = jarFile.getName();
if (name.endsWith(".jar") ? true : false) {
jars.add(jarFile);
}
}
}
}
调用
public static void main(String[] objs){
DynamicCompilerTool tool = new DynamicCompilerTool();
String outputFile = target.getAbsolutePath()+File.separator+"WebContent"+File.separator+"WEB-INF"+File.separator+"classes";
File cls=new File(outputFile);
if(!cls.exists()){
cls.mkdir();
}
String encoding = "utf-8";
boolean b = tool.compiler(encoding, javaProject.getAbsolutePath(), outputFile, diagnostics);
if(!b){
StringJoiner rs=new StringJoiner(System.getProperty("line.separator"));
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
rs.add(String.format("%s:%s[line %d column %d]-->%s%n", diagnostic.getKind(), diagnostic.getSource(), diagnostic.getLineNumber(),
diagnostic.getColumnNumber(),
diagnostic.getMessage(null)));
System.out.println("编译失败,原因:"+rs.toString());
}else{
System.out.println("编译成功");
}
}