欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java程序动态编译Java源文件

程序员文章站 2022-03-25 20:18:59
最近接触到公司一个项目,需要将生成的源码动态编译,记录下学习过程。 先贴出官网推荐写法: JavaCompiler.CompilationTask getTask(Writer out, JavaFileManager fileManager, DiagnosticListener

最近接触到公司一个项目,需要将生成的源码动态编译,记录下学习过程。

先贴出官网推荐写法:

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();

}