- 所有超级接口:
-
OptionChecker
,Tool
编译器在编译过程中可能会生成诊断信息(例如,错误消息)。如果提供了诊断监听器,诊断信息将被提供给监听器。如果未提供监听器,则诊断信息将以未指定的格式进行格式化并写入默认输出,即System.err
,除非另有规定。即使提供了诊断监听器,某些诊断信息可能不适合Diagnostic
中,并将被写入默认输出。
编译器工具具有关联的标准文件管理器,这是工具本地的文件管理器(或内置的)。可以通过调用getStandardFileManager来获取标准文件管理器。
只要满足下面方法中详细说明的任何附加要求,编译器工具就必须能够与任何文件管理器一起运行。如果未提供文件管理器,则编译器工具将使用标准文件管理器,例如由getStandardFileManager返回的文件管理器。
实现此接口的实例必须符合Java语言规范并生成符合Java虚拟机规范的类文件。这些规范的版本在Tool接口中定义。此外,支持SourceVersion.RELEASE_6或更高版本的此接口实例还必须支持注解处理
。
编译器依赖于两个服务:诊断监听器和文件管理器。尽管此包中的大多数类和接口定义了编译器(以及工具一般)的API,但接口DiagnosticListener、JavaFileManager、FileObject和JavaFileObject并不打算在应用程序中使用。相反,这些接口旨在被实现和用于为编译器提供定制服务,并因此为编译器定义了SPI。
此包中有许多类和接口旨在简化SPI的实现,以自定义编译器的行为:
-
StandardJavaFileManager
-
每个实现此接口的编译器都为操作常规文件提供了一个标准文件管理器。StandardJavaFileManager接口定义了用于从常规文件创建文件对象的附加方法。
标准文件管理器有两个目的:
- 自定义编译器读取和写入文件的基本构建块
- 在多个编译任务之间共享
重用文件管理器可能会减少扫描文件系统和读取jar文件的开销。尽管可能不会减少开销,但标准文件管理器必须能够处理多个连续编译,使以下示例成为推荐的编码模式:
File[] files1 = ... ; // 第一个编译任务的输入 File[] files2 = ... ; // 第二个编译任务的输入 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); Iterable<? extends JavaFileObject> compilationUnits1 = fileManager.getJavaFileObjectsFromFiles(
Arrays.asList
(files1)); compiler.getTask(null, fileManager, null, null, null, compilationUnits1).call(); Iterable<? extends JavaFileObject> compilationUnits2 = fileManager.getJavaFileObjects(files2); // 使用替代方法 // 重用相同的文件管理器以允许缓存jar文件 compiler.getTask(null, fileManager, null, null, null, compilationUnits2).call(); fileManager.close(); -
DiagnosticCollector
-
用于在列表中收集诊断信息,例如:
Iterable<? extends JavaFileObject> compilationUnits = ...; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call(); for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { System.out.format("第 %d 行的错误在 %s%n", diagnostic.getLineNumber(), diagnostic.getSource().toUri()); } fileManager.close();
-
ForwardingJavaFileManager
、ForwardingFileObject
和ForwardingJavaFileObject
-
无法使用子类化来覆盖标准文件管理器的行为,因为它是通过调用编译器上的方法而不是通过调用构造函数创建的。应使用转发(或委托)。这些类使得可以将大多数调用转发到给定的文件管理器或文件对象,同时允许自定义行为。例如,考虑如何记录对JavaFileManager.flush()的所有调用:
final Logger logger = ...; Iterable<? extends JavaFileObject> compilationUnits = ...; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null); JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) { @Override public void flush() throws IOException { logger.entering(StandardJavaFileManager.class.getName(), "flush"); super.flush(); logger.exiting(StandardJavaFileManager.class.getName(), "flush"); } }; compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
-
SimpleJavaFileObject
-
此类提供了一个基本的文件对象实现,可用作创建文件对象的基本构建块。例如,以下是如何定义一个代表存储在字符串中的源代码的文件对象:
/** * 用于表示来自字符串的源代码的文件对象。 */ public class JavaSourceFromString extends SimpleJavaFileObject { /** * 此“文件”的源代码。 */ final String code; /** * 构造一个新的JavaSourceFromString。 * @param name 此文件对象表示的编译单元的名称 * @param code 此文件对象表示的编译单元的源代码 */ JavaSourceFromString(String name, String code) { super(
URI.create
("string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); this.code = code; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } }
- 自1.6版本起:
- 1.6
- 参见:
-
Nested Class Summary
-
Method Summary
Modifier and TypeMethodDescriptiongetStandardFileManager
(DiagnosticListener<? super JavaFileObject> diagnosticListener, Locale locale, Charset charset) 返回此工具的标准文件管理器实现的新实例。getTask
(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options, Iterable<String> classes, Iterable<? extends JavaFileObject> compilationUnits) 使用给定的组件和参数创建编译任务的未来。Methods declared in interface javax.tools.OptionChecker
isSupportedOption
Methods declared in interface javax.tools.Tool
getSourceVersions, name, run
-
Method Details
-
getTask
JavaCompiler.CompilationTask getTask(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options, Iterable<String> classes, Iterable<? extends JavaFileObject> compilationUnits) 使用给定的组件和参数创建编译任务的未来。如CompilationTask接口中所述,编译可能尚未完成。如果提供了文件管理器,则必须能够处理
StandardLocation
中定义的所有位置。请注意,注解处理可以处理要编译的源代码的编译单元(通过
compilationUnits
参数传递),以及类文件,其名称通过classes
参数传递。- 参数:
-
out
- 用于编译器输出的Writer;如果为null
,则使用System.err
-
fileManager
- 文件管理器;如果为null
,则使用编译器的标准文件管理器 -
diagnosticListener
- 诊断监听器;如果为null
,则使用编译器默认的诊断报告方法 -
options
- 编译器选项,null
表示没有选项 -
classes
- 要由注解处理处理的类的名称,null
表示没有类名 -
compilationUnits
- 要编译的编译单元,null
表示没有编译单元 - 返回:
- 表示编译的对象
- 抛出:
-
RuntimeException
- 如果用户提供的组件中发生了无法恢复的错误。 cause 将是用户代码中的错误。 -
IllegalArgumentException
- 如果任何选项无效,或者给定的编译单元不是源类型
-
getStandardFileManager
StandardJavaFileManager getStandardFileManager(DiagnosticListener<? super JavaFileObject> diagnosticListener, Locale locale, Charset charset) 返回此工具的标准文件管理器实现的新实例。文件管理器将使用给定的诊断监听器生成任何非致命诊断。致命错误将使用适当的异常进行信号传递。如果在调用
flush
或close
后访问标准文件管理器,标准文件管理器将自动重新打开。标准文件管理器必须可与其他工具一起使用。- 参数:
-
diagnosticListener
- 用于非致命诊断的诊断监听器;如果为null
,则使用编译器默认的诊断报告方法 -
locale
- 格式化诊断时要应用的区域设置;null
表示默认区域设置 -
charset
- 用于解码字节的字符集;如果为null
,则使用平台默认值 - 返回:
- 标准文件管理器
-