知识大全 SE6调用编译器的两种方法[1]

Posted

篇首语:缥帙各舒散,前后互相逾。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 SE6调用编译器的两种方法[1]相关的知识,希望对你有一定的参考价值。

Java进阶:SE6调用编译器的两种方法[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  在很多Java应用中需要在程序中调用Java编译器来编译和运行 但在早期的版本中(Java SE 及以前版本)中只能通过tools jar中的 sun tools javac包来调用Java编译器 但由于tools jar不是标准的Java库 在使用时必须要设置这个jar的路径 而在Java SE 中为我们提供了标准的包来操作Java编译器 这就是javax tools包 使用这个包 我们可以不用将jar文件路径添加到classpath中了

  一 使用JavaCompiler接口来编译Java源程序

  使用Java API来编译Java源程序有很多方法 现在让我们来看一种最简单的方法 通过JavaCompiler进行编译

  我们可以通过ToolProvider类的静态方法getSystemJavaCompiler来得到一个JavaCompiler接口的实例

  JavaCompiler piler = ToolProvider getSystemJavaCompiler();

  JavaCompiler中最核心的方法是run 通过这个方法可以编译java源程序 这个方法有 个固定参数和 个可变参数(可变参数是从Jave SE 开始提供的一个新的参数类型 用type… argu表示) 前 个参数分别用来为java编译器提供参数 得到Java编译器的输出信息以及接收编译器的错误信息 后面的可变参数可以传入一个或多个Java源程序文件 如果run编译成功 返回

  int run(InputStream in OutputStream out OutputStream err String arguments)

  如果前 个参数传入的是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_pilerapi     public static void main(String args[]) throws IOException       JavaCompiler piler = ToolProvider getSystemJavaCompiler();    int results = piler run(null null null test java );    System out println((results == )? 编译成功 : 编译失败 );    // 在程序中运行test    Runtime 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       System out println( JavaCompiler测试成功! );     

  编译成功的输出结果

  编译成功

  JavaCompiler测试成功

  编译失败的输出结果

  test java: : 找不到符号

  符号 方法 printlnln(java lang String)

  位置 类 java io PrintStream

  System out printlnln( JavaCompiler测试成功! );

  ^

   错误

  编译失败

  二 使用StandardJavaFileManager编译Java源程序

  在第一部分我们讨论调用java编译器的最容易的方法 这种方法可以很好地工作 但它确不能更有效地得到我们所需要的信息 如标准的输入 输出信息 而在Java SE 中最好的方法是使用StandardJavaFileManager类 这个类可以很好地控制输入 输出 并且可以通过DiagnosticListener得到诊断信息 而DiagnosticCollector类就是listener的实现

  使用StandardJavaFileManager需要两步 首先建立一个DiagnosticCollector实例以及通过JavaCompiler的getStandardFileManager()方法得到一个StandardFileManager对象 最后通过CompilationTask中的call方法编译源程序

  在使用这种方法调用Java编译时最复杂的方法就是getTask 下面让我们讨论一下getTask方法 这个方法有如下所示的 个参数

  getTask(Writer out JavaFileManager fileManager   DiagnosticListener diagnosticListener   Iterable options   Iterable classes   Iterable pilationUnits)

  这些参数大多数都可为null 它们的含义所下

  ·out: 用于输出错误的流 默认是System err

  ·fileManager: 标准的文件管理

  ·diagnosticListener: 编译器的默认行为

  ·options: 编译器的选项

  ·classes 参与编译的class

  最后一个参数pilationUnits不能为null 因为这个对象保存了你想编译的Java文件

  在使用完getTask后 需要通过StandardJavaFileManager的getJavaFileObjectsFromFiles或getJavaFileObjectsFromStrings方法得到pilationUnits对象 调用这两个方法的方式如下

  Iterable getJavaFileObjectsFromFiles(  Iterable files)  Iterable getJavaFileObjectsFromStrings(  Iterable names)  String[] filenames = …;  Iterable pilationUnits =  fileManager getJavaFileObjectsFromFiles(Arrays asList(filenames));  JavaCompiler CompilationTask task = piler getTask(null fileManager   diagnostics options null pilationUnits);  最后需要关闭fileManager close();

  下面是一个完整的演示程序

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

  如果想得到具体的编译错误 可以对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: piler err not stmt  Kind: ERROR  Position:   Start Position:   End Position:   Source: test java  Message: test java: : 不是语句  Success: false

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

  Iterable options = Arrays asList( d d:\\\\ );  JavaCompiler CompilationTask task = piler getTask(null fileManager   diagnostics options null pilationUnits);

  在上面的例子中options处的参数为null 而要传递编译器的参数 就需要将options传入

  有时我们编译一个Java源程序文件 而这个源程序文件需要另几个Java文件 而这些Java文件又在另外一个目录 那么这就需要为编译器指定这些文件所在的目录

  Iterable options = Arrays asList( sourcepath d:\\\\src );

  上面的代码指定的被编译Java文件所依赖的源文件所在的目录

cha138/Article/program/Java/hx/201311/27239

相关参考

知识大全 SE6调用编译器的两种方法[2]

Java进阶:SE6调用编译器的两种方法[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  三

知识大全 在SE6中调用编译器的两种方法[4]

Java进阶:在SE6中调用编译器的两种方法[4]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 在SE6中调用编译器的两种方法[3]

Java进阶:在SE6中调用编译器的两种方法[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 在SE6中调用编译器的两种方法[2]

Java进阶:在SE6中调用编译器的两种方法[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 Java SE6调用Java编译器的两种新方法

JavaSE6调用Java编译器的两种新方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nbs

知识大全 Java调用Eclipse的编译器JDT

Java调用Eclipse的编译器JDT  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  想给项目

知识大全 .NET的动态编译与WS服务调用详解

.NET的动态编译与WS服务调用详解  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!这篇文章介绍了N

知识大全 ASP.NET预编译Web应用程序规避调用延迟

ASP.NET预编译Web应用程序规避调用延迟  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  A

知识大全 方法调用的绑定

  将一个方法调用同一个方法主体连接到一起就称为绑定(Binding)若在程序运行以前执行绑定(由编译器和链接程序如果有的话)就叫作早期绑定大家以前或许从未听说过这个术语因为它在任何程序化语言里都是不

知识大全 asp.net源程序编译为dll文件并调用过程

  使用csc命令将cs文件编译成dll的过程很多时候我们需要将cs文件单独编译成dll文件 操作如下:打开命令窗口>输入cmd到控制台>cd C:WINDOWSMic