一、使用JavaCompiler接口来编译Java源程式
  使用Java API来编译Java源程式有非常多方法,目前让我们来看一种最简单的方法,通过JavaCompiler进行编译。
  我们能通过ToolProvider类的静态方法getSystemJavaCompiler来得到一个JavaCompiler接口的实例。
  JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  JavaCompiler中最核心的方法是run。通过这个方法能编译java源程式。这个方法有3个固定参数和1个可变参数(可变参数是从Jave SE5开始提供的一个新的参数类型,用type… argu表示)。前3个参数分别用来为java编译器提供参数、得到Java编译器的输出信息及接收编译器的错误信息,后面的可变参数能传入一个或多个Java源程式文件。如果run编译成功,返回0。
  int run(InputStream in, OutputStream out, OutputStream err, String… arguments)
  如果前3个参数传入的是null,那么run方法将以标准的输入、输出代替,即System.in、System.out和System.err。如果我们要编译一个test.java文件,并将使用标准输入输出,run的使用方法如下:
  int results = tool.run(null, null, null, “test.java”);
  下面是使用JavaCompiler的完整代码:

import java.io.*;
import javax.tools.*;
public class test_compilerapi
{public static void main(String args[]) throws IOException{JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();int results = compiler.run(null, null, null, "test.java");System.out.println((results == 0)?"编译成功":"编译失败");// 在程式中运行testRuntime run = Runtime.getRuntime();Process p = run.exec("java test");BufferedInputStream in = new BufferedInputStream(p.getInputStream());BufferedReader br = new BufferedReader(new InputStreamReader(in));String s;while ((s = br.readLine()) != null)System.out.println(s);}
}
public class test
{public static void main(String[] args) throws Exception}

 编译成功的输出结果:
  编译成功
  JavaCompiler测试成功
  编译失败的输出结果:
test.java:9: 未找到符号
符号: 方法 printlnln(java.lang.String)
位置: 类 java.io.PrintStream
System.out.printlnln(“JavaCompiler测试成功!”);
^
1 错误
编译失败
  二、使用StandardJavaFileManager编译Java源程式
  在第一部分我们讨论调用java编译器的最容易的方法。这种方法能非常好地工作,但他确不能更有效地得到我们所需要的信息,如标准的输入、输出信息。而在Java SE6中最佳的方法是使用StandardJavaFileManager类。这个类能非常好地控制输入、输出,并且能通过DiagnosticListener得到诊断信息,而DiagnosticCollector类就是listener的实现。
  使用StandardJavaFileManager需要两步。首先建立一个DiagnosticCollector实例及通过JavaCompiler的getStandardFileManager()方法得到一个StandardFileManager对象。最后通过CompilationTask中的call方法编译源程式。
  在使用这种方法调用Java编译时最复杂的方法就是getTask,下面让我们讨论一下getTask方法。这个方法有如下所示的6个参数。

getTask(Writer out,JavaFileManager fileManager,
DiagnosticListener<? super JavaFileObject> diagnosticListener,
Iterable<String> options,
Iterable<String> classes,
Iterable<? extends JavaFileObject> compilationUnits)

  这些参数大多数都可为null。他们的含义所下。
o  ?out::用于输出错误的流,默认是System.err。
o  ?fileManager::标准的文件管理。
o  ?diagnosticListener: 编译器的默认行为。
o  ?options: 编译器的选项
o  ?classes:参和编译的class。
  最后一个参数compilationUnits不能为null,因为这个对象保存了你想编译的Java文件。
在使用完getTask后,需要通过StandardJavaFileManager的getJavaFileObjectsFromFiles或getJavaFileObjectsFromStrings方法得到compilationUnits对象。调用这两个方法的方式如下:.

Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(
Iterable<? extends File> files)
Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(
Iterable<String> names)
String[] filenames = …;
Iterable<? extends JavaFileObject> compilationUnits =
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(filenames));
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager,
diagnostics, options, null, compilationUnits);

  最后需要关闭fileManager.close();
  下面是个完整的演示程式。

import java.io.*;
import java.util.*;
import javax.tools.*;
public class test_compilerapi
{private static void compilejava() throws Exception{JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();// 建立DiagnosticCollector对象 DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);// 建立用于保存被编译文件名的对象// 每个文件被保存在一个从JavaFileObject继承的类中 Iterable<? extends JavaFileObject> compilationUnits = fileManager
.getJavaFileObjectsFromStrings(Arrays asList("test3.java"));JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager,
diagnostics, null, null, compilationUnits);// 编译源程式boolean success = task.call();fileManager.close();System.out.println((success)?"编译成功":"编译失败");}public static void main(String args[]) throws Exception}

如果想得到具体的编译错误,能对Diagnostics进行扫描,代码如下:

for (Diagnostic diagnostic : diagnostics.getDiagnostics())
System.out.printf(
"Code: %s%n" +
"Kind: %s%n" +
"Position: %s%n" +
"Start Position: %s%n" +
"End Position: %s%n" +
"Source: %s%n" +
"Message: %s%n",
diagnostic.getCode(), diagnostic.getKind(),
diagnostic.getPosition(), diagnostic.getStartPosition(),
diagnostic.getEndPosition(), diagnostic.getSource(),
diagnostic.getMessage(null));被编译的test.java代码如下:
public class test
{public static void main(String[] args) throws Exception{aa; //错误语句System.out.println("JavaCompiler测试成功!");}
}

  在这段代码中多写了个aa,得到的编译错误为:

Code: compiler.err.not.stmt
Kind: ERROR
Position: 89
Start Position: 89
End Position: 89
Source: test.java
Message: test.java:5: 不是语句
Success: false

  通过JavaCompiler进行编译都是在当前目录下生成.class文件,而使用编译选项能改动这个默认目录。编译选项是个元素为String类型的Iterable集合。如我们能使用如下代码在D盘根目录下生成.class文件。

Iterable<String> options = Arrays.asList("-d", "d:");
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager,
diagnostics, options, null, compilationUnits); 

  在上面的例子中options处的参数为null,而要传递编译器的参数,就需要将options传入。
  有时我们编译一个Java源程式文件,而这个源程式文件需要另几个Java文件,而这些Java文件又在另外一个目录,那么这就需要为编译器指定这些文件所在的目录。
Iterable options = Arrays.asList(“-sourcepath”, “d:src”);
  上面的代码指定的被编译Java文件所依赖的源文件所在的目录。

JavaCompiler相关推荐

  1. 解决IDEA自动重置LanguageLevel和JavaCompiler版本的问题

    使用IDEA时,导入的Maven项目默认的LanguageLevel和JavaCompiler都是1.5,1.5的情况下连最简单的@Override注解都不支持,所以项目可能出现一堆错. 虽然在项目上 ...

  2. java 上下文加载器_如何将JDK6 ToolProvider和JavaCompiler与上下文类加载器一起使用?...

    我的用例是使用JDK 6中提供的ToolProvider和 JavaCompiler类从java程序编译生成的源文件.源文件包含对上下文类加载器中的类的引用(它在J2EE容器中运行),但不包含在系统类 ...

  3. 使用javax.tools.JavaCompiler根据字符串内容动态生成新的Java类并编译成.class

    测试代码: package dynamicproxy;public class DynamicProxy implements IHelloWorld {IHelloWorld helloWorld; ...

  4. compiler java_使用JavaCompiler编译java源文件

    从1.6版本的JDK开始,JDK提供了标准的包可以方便的调用JVM的编译器,可以方便的使用JVM的编译器来编译java源文件.JDK提供的调用接口是JavaCompiler类,该类在JDK的tools ...

  5. java compiler类_利用 JavaCompiler 编译 Java 类文件

    1.[代码]DiagnosticCollectorCompile.java import java.io.IOException; import java.util.Arrays; import ja ...

  6. Java WebIDE:CodeMirror+Vue+JavaCompiler

    课上JavaEE,老师直接用了大佬的教程. Vue + Spring Boot 项目实战: https://blog.csdn.net/Neuf_Soleil/article/details/8892 ...

  7. JavaCompiler实战:将Java源代码字符串动态编译成java类

    .首先我们来认识一下 java中的一个对象 JavaCompiler JavaCompiler : 不知道肯定很陌生,其实这个api出来很久了,他是jdk6的特性,用来编译java的源程式的,详细介绍 ...

  8. IDEA maven变更后导致自动重置LanguageLevel和JavaCompiler版本的问题

    使用IDEA时,导入的Maven项目默认的LanguageLevel和JavaCompiler都是1.5,1.5的情况下连最简单的@Override注解都不支持. 虽然可以通过setting中可以修改 ...

  9. Eclipse创建web工程时,报错Dynamic Web Module 3.0 requires Java 1.6 or newer.

    报错: 解决方案: 1.打开eclipse工具栏window->preferences 2.打开java->compiler 3.选择compiler compliance level在1 ...

最新文章

  1. [微信小程序]滚动选择器
  2. webstorm代码行数统计_【Rust每周一库】Tokei 统计代码行数等信息的实用工具
  3. 一些SqlServer常见和入门操作
  4. [BUUCTF-pwn]——picoctf_2018_shellcode
  5. windows文件中的中文在ubuntu下乱码(小弟参考了许多都不行,这个绝对行啊) .
  6. 工作流实战_27_flowable 自定义sql查询
  7. 【STM32】【STM32CubeMX】STM32CubeMX的使用之六:定时器配置输出PWM,实现变色呼吸灯
  8. 三七互娱Q3归母净利润超预告上限,三大战略迎提速契机
  9. c++频繁读取数据会丢失_透析中会丢失什么营养?透析日的饮食需要注意什么?...
  10. geoserver发布瓦片数据_geoserver地图发布服务教程(3)——快速配置矢量样式
  11. 利用通用权限管理系统底层解决数据从不同库的导入导出问题
  12. MacOS Big Sur 11.5.2 (20G95) OC 0.7.2 / Cl 5138 / PE 三分区原版黑苹果镜像
  13. 学完python可以当黑客吗_想当黑客吗?我教你啊!精心整理最简单的黑客入门——PYTHON教程,免费系统又经典...
  14. 1.4 批量生成Oracle建表语句
  15. java 16进制_JAVA 十六进制与字符串的转换
  16. 关于sentaurus使用感
  17. 汇编语言和本地代码及通过编译器输出汇编语言的源代码
  18. #英语# 表示人的名词后缀论文文献
  19. wp8.1 java_巨硬的内部比较——WP8.1版本与WP10系统对比(以lumia640为例)
  20. 线性代数Python计算:矩阵对角化

热门文章

  1. CA运作模式-认证与过期吊销
  2. 2021-4-8学习笔记
  3. linux驱动程序设计21 Linux设备驱动的调试
  4. 1、HotSpot And OpenJDK And OracleJDK And JER区别
  5. deeplearning4j的官网
  6. 天高任鸟飞,在你还苦闷Android出路时,总有人在系统钻研为高级开发做准备
  7. 辅助小工具---FooView
  8. 编程之美--游戏之乐--1.3一摞烙饼的排序
  9. Ecshop实现注册页面手机号唯一的验证
  10. 啊啊啊啊啊啊啊啊啊啊啊啊啊啊(一篇自述)