java编译器API——使用编译工具

【0】README

0.1)以下内容转自: http://suntips.iteye.com/blog/69002

0.2)for basic java compiler API, please visit  http://blog.csdn.net/pacosonswjtu/article/details/50718494


1)当你需要更好的处理这些结果时,你可以使用第二种方法来访问编译器. 

更特别的是,这第二种方式允许开发者将编译输出结果用一种更有意义的方式表现出来,而不是简单的那种送往stdeer的错误文本. 利用 StandardJavaFileManager 类我们有这种更好的途径使用编译器. 这个文件管理器提供了一种方式,用来处理普通文件的输入输出操作. 它同时利用 DiagnosticListener 实例来报告调试信息. 你需要使用的 DiagnosticCollector 类其实是监听器的一种实现.

2)在搞清楚你需要编译什么之前,你需要一个文件管理器. 生成一个管理器基本上需要两步:  创建一个DiagnosticCollector 和 使用 JavaCompiler 的 getStandardFileManager() 方法获得一个文件管理器. 把DiagnosticListener 对象传入 getStandardFileManager() 方法中. 这个监听器可以报告一些非致命的问题,到后来你可以选择性的通过把它传入 getTask() 方法来和编译器共享. 

DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); 
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, aLocale, aCharset);

3)你也可以往这个调用里传入一个 null 值的诊断器,但这样也就等于用以前的编译器方法了.

3.1)在详细查看 StandardJavaFileManager 之前 ,编译过程涉及到 JavaCompiler 的一个方法叫做 getTask() . 它有六个参数,返回一个叫做 CompilationTask  内部类的实例: 

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

3.2)缺省情况下,大部分它的参数可以是 null.

* out: System.err 
* fileManager: compiler's standard file manager
* diagnosticListener: compiler's default behavior
* options: no command-line options to compiler
* classes: no class names for annotation processing

3.3)最后一个参数 compilationUnits 却是不能够为null ,因为它是你要去编译的东西. 它把我们又带回了StandardJavaFileManager 类.注意这个参数类型: Iterable<? extends JavaFileObject> .  StandardJavaFileManager 有两个方法返回这样的结果. 你可以使用一个文件对象的List或者String 对象的List,用它们来表示文件名:  

Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) 
Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings( Iterable<String> names)

3.4)并不仅仅 List ,实际上,任何一个能够标识需要编译的内容的集合的 Iterable 都可以.  List 出现在这里只是因为它容易生成: 

String[] filenames = ...; 
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(filenames)); 

3.5)现在你有了编译源文件的所有的必要的信息. 从 getTask( ) 返回的 JavaCompiler.CompilationTask  实现了Callable .接口 这样,想让任务开始就去调用call()方法. 

JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, compilationUnits);
Boolean success = task.call(); 

4)如果没有编译警告和错误,这个call() 方法会编译所有的 compilationUnits 变量指定的文件,以及有依赖关系的可编译的文件. 

想要知道是否所有的都成功了,去查看一下返回的 Boolean 值. 只有当所有的编译单元都执行成功了,这个 call() 方法才返回 Boolean.TRUE  . 一旦有任何错误,这个方法就会返回 Boolean.FALSE .

在展示运行这个例子之前,让我们添加最后一个东西,DiagnosticListener , 或者更确切的说, DiagnosticCollector .的实现类.把这个监听器当作getTask()的第三个参数传递进去,你就可以在编译之后进行一些调式信息的查询了. 

for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { System.console().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)); 
}

5)在最后,你应该调用管理器的close() 方法.

6)把所有的放在一起,就得到的了下面的程序,让我们重新编译Hello(StandardJavaFileManagerTest)类.  

package com.corejava.chapter10_2;import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Locale;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;public class AdvancedJavaCompiler
{public static void main(String[] args) throws IOException{JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); // 返回java 编译器// DiagnosticCollector 是监听器的一种实现DiagnosticCollector<JavaFileObject>  diagnostics = new DiagnosticCollector<>(); // java 文件管理器StandardJavaFileManager manager = compiler.getStandardFileManager(diagnostics, Locale.CHINA, Charset.forName("UTF-8")); /* Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) */// 所要编译的源文件Iterable<? extends JavaFileObject> compilationUnits = manager.getJavaFileObjects("com/corejava/chapter10_2/StandardJavaFileManagerTest.java");CompilationTask task = compiler.getTask(null, manager, diagnostics, null, null, compilationUnits);// 如果没有编译警告和错误,这个call() 方法会编译所有的 compilationUnits 变量指定的文件,以及有依赖关系的可编译的文件.Boolean suc = task.call();/* 只有当所有的编译单元都执行成功了,这个 call() 方法才返回 Boolean.TRUE  . 一旦有任何错误,这个方法就会返回 Boolean.FALSE .* 在展示运行这个例子之前,让我们添加最后一个东西,DiagnosticListener , 或者更确切的说,  DiagnosticCollector .的实现类.* 把这个监听器当作getTask()的第三个参数传递进去,你就可以在编译之后进行一些调式信息的查询了. */for(Diagnostic diagnostic : diagnostics.getDiagnostics()){System.console().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));}manager.close();System.out.println("success : " + suc);}
}


7)然而,如果你把 println  方法改成书写错误的 pritnln 方法,当你运行时你会得到下面的信息: 

E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter10_2.AdvancedJa 
vaCompiler 
Code: compiler.err.cant.resolve.location.args 
Kind: ERROR 
Position: 139 
Start Position: 129 
End Position: 147 
Source: RegularFileObject[com\corejava\chapter10_2\StandardJavaFileManagerTest.java] 
Message:  找不到符号 符号:   方法 printnl(java.lang.String) 位置: 类型为java.io.PrintStream的变量 out 
success : false


Attention) for source code about instances above, please visit  https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter10/10_2

使用Compiler API,你可以实现比在这篇简要的提示介绍的更多的事情. 例如,你可以控制输入输出的目录或者在集成编译器里高亮一些编译错误. 现在,向 Java Compiler API表示感谢,你可以使用标准API了. For more information on the Java Compiler API and JSR 199, see the JSR 199 specification.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331379.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 线程同步总结

一、synchronized&#xff08;1&#xff09;synchronized方法 &#xff08;2&#xff09;synchronized块 二、Lock 注意&#xff1a;及时释放Lock锁&#xff0c;否则会出现死锁&#xff0c;通常在finally代码释放锁 &#xff08;1&#xff09;ReentrantLock 实现…

aws es方案_AWS Elasticsearch后模式

aws es方案碰巧我们在SaaS版本的LogSentinel上遇到了生产问题–我们的Elasticsearch停止了对新数据编制索引。 由于Elasticsearch只是辅助存储&#xff0c;因此没有数据丢失&#xff0c;但这给我们的客户带来了一些问题&#xff08;他们无法在其仪表板上看到实时数据&#xff0…

java注解总结

【0】README 0.1&#xff09;本文主要对 java 注解做总结&#xff1b; 【1】处理注解的级别 level1&#xff09; 在运行期级别处理注解&#xff1a; http://blog.csdn.net/pacosonswjtu/article/details/50719361level2&#xff09;在源码级别处理注解&#xff1a; http://b…

Java 类加载总结

一、类加载过程 装载链接验证准备解析初始化二、类初始化情况 1&#xff09;创建类的实例&#xff0c;也就是new一个对象 2&#xff09;访问某个类或接口的静态变量&#xff0c;或者对该静态变量赋值 3&#xff09;调用类的静态方法 4&#xff09;反射&#xff08;Class.…

maven依赖管理_依赖管理和Maven

maven依赖管理Maven伟大而成熟。 几乎所有事物都总有解决方案。 您可能在组织项目上遇到的主要情况是依赖管理。 而不是每个项目都具有自己的依赖关系&#xff0c;您需要一种集中的方式来继承那些依赖关系。 在这种情况下&#xff0c;您可以在父舞会上声明托管依赖项。 在我的…

JavaBean 持久化

【0】README 0.1&#xff09;本文文字描述转自 core java volume 2&#xff0c;旨在学习 JavaBean 持久化 的基础知识&#xff1b; 0.2&#xff09;本文所有源代码荔枝均为原创&#xff1b; 0.3&#xff09; for complete souce code, please visit https://github.com/pa…

apache kafka_Apache Kafka消费者再平衡

apache kafka消费者重新平衡决定哪个消费者负责某个主题的所有可用分区的哪个子集。 例如&#xff0c;您可能有一个包含20个分区和10个使用者的主题。 在重新平衡结束时&#xff0c;您可能希望每个使用者都从2个分区中读取数据。 如果关闭了这些使用者中的10个&#xff0c;则可…

Java 注解总结

一、注解定义 注解早在J2SE1.5就被引入到Java中&#xff0c;主要提供一种机制&#xff0c;这种机制允许程序员在编写代码的同时可以直接编写元数据。 二、元注解 Target 说明了被修饰的注解的应用范围&#xff0c;也就是被修饰的注解可以用来注解哪些程序元…

编译原理三大经典书籍(龙书 虎书 鲸书)

以下内容转自&#xff1a; http://blog.csdn.net/skymingst/article/details/7436892 1、龙书&#xff08;Dragon book&#xff09; 英文名&#xff1a;Compilers: Principles,Techniques,and Tools 作者&#xff1a;Alfred V.Aho,Ravi Sethi,Jeffrey D.Ullman 中文名&…

两个时间之间是多少小时_那是两个小时我不会回来

两个时间之间是多少小时正如我之前关于linting主题所说的 &#xff0c;花时间修改代码的好处很有限&#xff0c;因为自动工具告诉您这样做。 更糟糕的是&#xff0c;这些工具并非万无一失。 例如&#xff0c;我们一直在针对完美无害的try-with-resources构造周围的SpotBugs警告…

java的类载入器

【0】README 0.1&#xff09;本文文字转自&#xff1a; 深入剖析tomcat&#xff0c; 旨在 理解 jvm 的类载入器&#xff1b; 【1】 jvm的类载入器相关 1&#xff09;jvm 使用了3种类载入器来载入所需要的类&#xff1a;分别是引导类载入器&#xff08;bootstrap class load…

Java 代理总结

一、代理 为其他对象提供一种代理以便控制对这个对象的访问。 &#xff08;1&#xff09;静态代理 &#xff08;2&#xff09;动态代理 1&#xff09;JDK自带的动态代理 2&#xff09;javaassist字节码操作库实现 3&#xff09;CGLIB 4&#xff09; ASM&#xff08;底层…

分解因数 递归_递归分解WAR文件

分解因数 递归抽象 是否曾经需要分解WAR文件以及分解WAR文件中的所有JAR文件&#xff1f; 是的&#xff0c;我也是&#xff01; 我写了ferris-war-exploder来爆炸&#xff1a; 一个JAR文件 一个WAR文件&#xff0c;它找到的每个JAR文件也会爆炸。 包含每个JAR文件&#xff…

jvm(2)-java内存区域

【0】README 0.1&#xff09;本文转自 深入理解jvm&#xff0c; 旨在学习 java内存区域 的基础知识&#xff1b; 【1】运行时数据区域 1&#xff09;jvm 所管理的内存将会包括以下几个运行时数据区域 1.1&#xff09;方法区&#xff1b;&#xff08;线程共享&#xff09; 1.2&…

Java Socket编程总结

一、网络API InetAddress     用于标识网络上的硬件资源&#xff0c;主要是IP地址 URL         统一资源定位符&#xff0c;通过URL可以直接读取或写入网络上的数据Sockets      使用TCP协议实现的网络通信Socket相关的类Datagram     使用UDP协议&am…

java插入排序_Java程序要插入排序

java插入排序Java程序插入示例的排序。 显示了示例仿真以及时间复杂度。 插入排序是一种简单的排序算法&#xff0c;可以一次构建一个最终的排序数组&#xff08;或列表&#xff09;。 它比冒泡排序有效得多&#xff0c;并且在大型列表上的效率比快速排序 &#xff0c;堆排序或…

jvm(2)-JVM内存的设置(解决eclipse下out of memory问题)

【0】README 0.1&#xff09;本文转自&#xff1a; http://blog.csdn.net/sjf0115/article/details/8889201 一、JVM内存的设置的原理 默认的java虚拟机的大小比较小&#xff0c;在对大数据进行处理时java就会报错&#xff1a;java.lang.OutOfMemoryError。 设置jvm内存的方…

Java Servlet总结

一、Servlet简介 Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称&#xff0c;称为小服务程序或服务连接器&#xff0c;用Java编写的服务器端程序&#xff0c;主要功能在于交互式地浏览和修改数据&#xff0c;生成动态Web内容。狭义的Servlet是指Java语言实…

java oca_OCA第1部分中的Java难题

java oca我在业余时间正在阅读Mala Gupta的Oracle认证Java SE程序员助理书&#xff0c;我对所学到的一些新知识感到惊讶。 有时候他们真的没有道理&#xff0c;有时候他们说得通&#xff0c;但真的让人惊讶。 因此&#xff0c;在本系列文章中&#xff0c;我想将它们共享为“ Ja…

jvm(1)-走进java

【0】README0.1&#xff09;本文转自 深入理解 jvm&#xff0c;旨在了解 java 体系结构&#xff1b;【1】java技术体系1&#xff09; Sun 官方所定义的java 技术系统包括以下几个组成部分&#xff1a; java 程序设计语言&#xff1b;各种硬件平台上的java 虚拟机&#xff1b;Cl…