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

先贴出官网推荐写法:

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

}

Java程序动态编译Java源文件的更多相关文章

  1. JAVA之动态编译

    通过Java动态生成class文件 今天说下JAVA中的动态编译,这个功能根据我现在的了解好像没有见到过用的,我Jio的吧,现在的一些在线代码编缉器可以用到了,这个具体我也不是很清楚.感兴趣的大家可以 ...

  2. 深入理解Java的动态编译

    前提 笔者很久之前就有个想法:参考现有的主流ORM框架的设计,造一个ORM轮子,在基本不改变使用体验的前提下把框架依赖的大量的反射设计去掉,这些反射API构筑的组件使用动态编译加载的实例去替代,从而可 ...

  3. DOS环境下含包并引用第三方jar的java程序的编译及运行

    DOS环境下含包并引用第三方jar的java程序的编译及运行 1.程序目录机构 bin:class文件生成目录 lib:第三方jar包目录 src:源程序文件目录 2.程序代码: 3.程序编译 jav ...

  4. Java初学者作业——编写 Java 程序,定义 Java 类 (Point) 用来表示坐标,坐标范围在(0,0)到(100,100)以内,并显示合法的坐标在控制台。

    返回本章节 返回作业目录 需求说明: 编写 Java 程序,定义 Java 类 Point 用来表示坐标,坐标范围在(0,0)到(100,100)以内,并显示合法的坐标在控制台. 实现思路: 定义 P ...

  5. IT兄弟连 Java语法教程 编译Java程序

    编写好Java程序的源代码后,接下来就应该编译该Java源文件来生成字节码文件了. 编译Java程序需要使用JDK中提供的javac命令,因为已经把javac命令所在的路径添加到了系统的Path环境变 ...

  6. [学习笔记]java基础Java8SE开发环境搭建、第一个Java Hello World、Java程序的编译与执行

    本文作者:sushengmiyan 本文地址:http://blog.csdn.net/sushengmiyan/article/details/25745945 内容简介: ------------ ...

  7. cmd命令对java程序进行编译时出现:编码GBK的不可映射字符

    原因:由于JDK是国际版的,在编译的时候,如果我们没有用-encoding参数指定JAVA源程序的编码格式,则java.exe首先获得我们才做系统默认采用的编码格式,也即在编译JAVA程序时,若我们不 ...

  8. Java的动态编译、动态加载、字节码操作

    想起来之前做的一个项目:那时候是把需要的源代码通过文件流输出到一个.java文件里,然后调用sun的Comipler接口动态编译成.class文件,然后再用专门写的一个class loader加载这个 ...

  9. (三)java程序的编译和执行

    编写java程序 eg class Demo { /* * 程序运行的入口 */ public static void main(String[] args) { System.out.println ...

随机推荐

  1. RQNOJ 622 最小重量机器设计问题:dp

    题目链接:https://www.rqnoj.cn/problem/622 题意: 一个机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得. w[i][j]是从供应商j处购得的部件i的重量, ...

  2. 分享知识-快乐自己:Hibernate 中 get() 和 load()、sava、update、savaOrUpdate、merge,不同之处及执行原理?

    1):Hibernate 中 get()  和 load() 有什么不同之处? 1)Hibernate的 get方法,会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在缓存中查 ...

  3. 51nod【1196】字符串的数量

    超级神题! 有n种字符,若此种字符的编号( \(1\) ~ \(n\)),\(i*2>n\),则他后面可接任意字符.若不是,则他后面接的字符编号至少要是他的两倍. 问长度为m的字符串的个数. 这 ...

  4. SENet(Squeeze-and-Excitation Networks)算法笔记---通过学习的方式来自动获取到每个特征通道的重要程度,然后依照这个重要程度去提升有用的特征并抑制对当前任务用处不大的特征

    Momenta详解ImageNet 2017夺冠架构SENet 转自机器之心专栏 作者:胡杰 本届 CVPR 2017大会上出现了很多值得关注的精彩论文,国内自动驾驶创业公司 Momenta 联合机器 ...

  5. 菜鸟快速自学java00之变量类型

    ---恢复内容开始--- 菜鸟快速自学java00之变量类型 一.诉苦 自己成为了Java中的一只菜鸟,而且已经菜了好多天了,我为什么会这么菜?归根结底,还是觉得自己在累计知识的同时,没有做好笔记,导 ...

  6. codeforces 660C C. Hard Process(二分)

    题目链接: C. Hard Process time limit per test 1 second memory limit per test 256 megabytes input standar ...

  7. ACM学习历程—HDU 5317 RGCDQ (数论)

    Problem Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more an ...

  8. 数据结构与算法(5)----->二叉树

    1.  概念 二叉树节点的结构: class Node{ int value; // value表示二叉树的节点值 Node left; Node right; // left和right表示二叉树的 ...

  9. Flashback Database 闪回数据库

    一.  Flashback Database 说明 Flashback Database 功能非常类似与 RMAN 的不完全恢复, 它可以把整个数据库回退到过去的某个时点的状态, 这个功能依赖于 Fl ...

  10. 更换mysql数据目录后出现 ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) 的解决办法

    服务器上的mysql默认数据目录为/var/lib/mysql/,同时服务器的/空间不是很大,而近期又有大量的日志需要导入进行分析,时常搞得/的空间捉襟见肘,晚上一狠心就想把mysql的数据目录转移到 ...