《java下第八章编译器API.ppt》由会员分享,可在线阅读,更多相关《java下第八章编译器API.ppt(33页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第八章编译器编译器API学习目标学习目标编译器概述,了解API能够实现的功能。能够熟练使用ToolProvider获得系统默认编译器,并动态完成编译操作。熟练应用StandardJavaFileManager管理相关的输入和输出,以及编译非文本文件。能够运用DiagnosticListener监听、收集编译过程中的诊断信息。范例导入范例导入程序代码的自我复制和自我修改是一种非常强大的能力,但这种能力常被滥用来制造病毒,以至于现代操作系统通常不允许修改程序的代码段和禁用调用栈的执行权限来保证代码的安全性。这使得通过修改自身代码来实现某种逻辑的合理编程方法受到了限制。而JDK 1.6赋予了程序员在
2、运行时刻产生并编译Java源代码的能力,这和Java的反射机制结合在一起,使得Java程序可以在运行过程中产生新类,替换旧类,动态修改自身组件以进行自适应优化运行时刻的性能。编译器编译器APIAPI概述概述-1-1 JDK 1.6 提供了在运行时调用编译器的 API,后面我们将假设把此 API 应用在 JSP 技术中。在传统的 JSP 技术中,服务器处理 JSP 通常需要进行下面六个步骤:、分析 JSP 代码、生成 Java 代码、将 Java 代码写入存储器、启动另外一个进程并运行编译器编译 Java 代码、将类文件写入存储器、服务器读入类文件并运行;但如果采用运行时编译,可以同时简化步骤
3、4 和 5,节约新进程的开销和写入存储器的输出开销,提高系统效率。编译器编译器APIAPI概述概述-2-2 新 API 的第二个新特性是可以编译抽象文件,理论上是任何形式的对象,只要该对象实现了特定的接口。第三个新特性是可以收集编译时的诊断信息。由此可见编译器API产生主要是面向热部署或者增量编译这样的场合,目的是增强Java和JVM的交互性。ToolProviderToolProvider类类 ToolProvider类为找出Tool提供了方法,例如,编译器的提供者。成员方法:public static JavaCompiler getSystemJavaCompiler()public s
4、tatic ClassLoader getSystemToolClassLoader()ToolTool接口接口 Tool接口是JavaCompiler接口的父接口,定义了命令行工具的共同的接口。成员方法:public Set getSourceVersions()public int run(InputStream in,OutputStream out,OutputStream err,String.arguments)动态编译练习动态编译练习 练习:编写一个java源文件Hello.java,然后写一段代码完成对Hello.java文件的动态编译和运行。程序清单:Hello.java 。
5、public class Hello public static void main(String args)System.out.println(Hello World!);System.out.println(你好,世界!);使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-1-1 JDK 1.6 的编译器 API 强大之处在于,它可以编译的源文件的形式并不局限于文本文件。JavaCompiler 类依靠文件管理服务可以编译多种形式的源文件。比如直接由内存中的字符串构造的文件,或者是从数据库中取出的文件。如果要使用 JavaFil
6、eManager,就必须构造 CompilationTask。JDK 1.6 提供了 JavaCompiler.CompilationTask 类来封装一个编译操作。这个类可以通过JavaCompiler的getTask方法得到。使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-2-2 JavaCompiler接口代表Java的编译器,方法如下:public StandardJavaFileManager getStandardFileManager(DiagnosticListener diagnosticListener,Loca
7、le locale,Charset charset)使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-3-3public JavaCompiler.CompilationTask getTask(Writer out,JavaFileManager fileManager,DiagnosticListener diagnosticListener,Iterable options,Iterable classes,Iterable compilationUnits)使用使用StandardJavaFileManagerStandard
8、JavaFileManager编译编译-4-4 JavaFileManager.Location描述文件对象地址,用于由文件管理器确定安置或搜寻文件对象。方法如下:public String getName()public boolean isOutputLocation()使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-5-5 StandardLocation枚举是JavaFileManager.Location接口的实现。public static final StandardLocation ANNOTATION_PROCES
9、SOR_PATH public static final StandardLocation CLASS_OUTPUT public static final StandardLocation CLASS_PATH使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-6-6public static final StandardLocation PLATFORM_CLASS_PATH public static final StandardLocation SOURCE_OUTPUT public static final Standard
10、Location SOURCE_PATH 使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-7-7 JavaFileManager是文件管理器,这个类可以很好地控制输入、输出。它为运行在JVM编程语言来源和类文件的工具。在文件管理器中,文件意味规则文件的抽象和数据的其他来源。成员方法:public FileObject getFileForInput(JavaFileManager.Location location,String packageName,String relativeName)throws IOException使用
11、使用StandardJavaFileManagerStandardJavaFileManager编译编译-8-8public JavaFileObject getJavaFileForInput(JavaFileManager.Location location,String className,JavaFileObject.Kind kind)throws IOExceptionpublic FileObject getFileForOutput(JavaFileManager.Location location,String packageName,String relativeName,
12、FileObject sibling)throws IOException使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-9-9public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location,String className,JavaFileObject.Kind kind,FileObject sibling)throws IOExceptionpublic Iterable list(JavaFileManager.Location loc
13、ation,String packageName,Set kinds,boolean recurse)throws IOException使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-10-10public void flush()throws IOExceptionpublic void close()throws IOException 其它方法参照API文档。使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-11-11 StandardJavaFileManager
14、接口是JavaFileManager接口的子接口,定义的是基于的标准Java文件管理器。成员方法:public Iterable getLocation(JavaFileManager.Location location)public void setLocation(JavaFileManager.Location location,Iterable path)throws IOException使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-12-12public Iterable getJavaFileObjects(File
15、.files)public Iterable getJavaFileObjects(String.names)public Iterable getJavaFileObjectsFromFiles(Iterable files)public Iterable getJavaFileObjectsFromStrings(Iterable names)使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-13-13 练习:测试文件管理器的JavaFileManager.Location地址的默认值,然后进行设置。练习:分别使用JavaFile
16、Manager和StandardJavaFileManager来获得FileObject对象和JavaFileObject对象。使用使用StandardJavaFileManagerStandardJavaFileManager编译编译-14-14 JavaCompiler.CompilationTask表示编译任务的接口。编译任务尚未开始。要开始任务,需要调用 call 方法,且一个编译任务只能调用一次call方法。成员方法:public Boolean call()练习:使用JavaCompiler.CompilationTask执行编译任务。使用使用StandardJavaFileMan
17、agerStandardJavaFileManager编译编译-15-15 我们在前面已经讲过JDK 1.6 的编译器 API 强大之处在于,它可以编译的源文件的形式并不局限于文本文件。JavaCompiler 类依靠文件管理服务可以编译多种形式的源文件。比如直接由内存中的字符串构造的文件,或者是从数据库中取出的文件,只要这些文件实现了特定的接口,这个接口就是FileObject。成员方法:public CharSequence getCharContent(boolean ignoreEncodingErrors)throws IOException使用使用StandardJavaFileM
18、anagerStandardJavaFileManager编译编译-16-16 JavaFileObject接口是FileObject接口的子接口,用于描述一个Java文件对象。SimpleJavaFileObject类实现了JavaFileObject接口,为 JavaFileObject 中的大多数方法提供简单实现。应子类化此类并用作 JavaFileObject 实现的基础。子类可以重写此类任意方法的实现和规范。构造方法:protected SimpleJavaFileObject(URI uri,JavaFileObject.Kind kind)使用使用StandardJavaFile
19、ManagerStandardJavaFileManager编译编译-17-17 练习:定义一个MyJavaFileObject类,做SimpleJavaFileObject类的子类,用于描述一个Java文件对象。练习:编译非文本形式的源文件,将内存中的一段字符内容编译成Java文件。编译器的诊断信息编译器的诊断信息-1-1 第三个新增加的功能,是监听、收集编译过程中的诊断信息。诊断信息,通常指错误、警告或是编译过程中的详尽输出。JDK 1.6 通过 Listener 机制,获取这些信息。DiagnosticListener接口主要用于接收来自编译器的诊断信息。成员方法:public void
20、 report(Diagnostic diagnostic)编译器的诊断信息编译器的诊断信息-2-2 DiagnosticCollector类是DiagnosticListener的实现类,它提供了将诊断收集到一个列表中的简单方法。成员方法:public ListDiagnostic getDiagnostics()public void report(Diagnostic diagnostic)编译器的诊断信息编译器的诊断信息-3-3 Diagnostic.Kind枚举用于描述诊断的种类,例如,错误或者警告。成员:public static final Diagnostic.Kind ERR
21、ORpublic static final Diagnostic.Kind WARNINGpublic static final Diagnostic.Kind MANDATORY_WARNINGpublic static final Diagnostic.Kind NOTEpublic static final Diagnostic.Kind OTHER编译器的诊断信息编译器的诊断信息-4-4 Diagnostic接口描述一个诊断信息。诊断通常报告源文件中指定位置处的问题。但是,并非所有的诊断都与位置或文件关联。位置是指距离文件开始位置的字符偏移量(从 0 开始)。负值(除 NOPOS 以外
22、)不是有效位置。行号和列号从 1 开始。负值(除 NOPOS 以外)和 0 不是有效的行号或列号。成员:public static final long NOPOS编译器的诊断信息编译器的诊断信息-5-5成员方法:public Diagnostic.Kind getKind()public S getSource()public long getLineNumber()public long getColumnNumber()public String getCode()public long getPosition()public String getMessage(Locale locale)编译器的诊断信息编译器的诊断信息-6-6 练习:编写一个有错误java源文件ErrorSource.java,然后写一段代码完成对ErrorSource.java文件进行动态编译,并诊断出所有的出错信息。小结小结 JDK 1.6 的编译器新特性,使得开发者可以更自如的控制编译的过程,这给了工具开发者更加灵活的自由度。通过 API 的调用完成编译操作的特性,使得开发者可以更方便、高效地将编译变为软件系统运行时的服务。而编译更广泛形式的源代码,则为整合更多的数据源及功能提供了强大的支持。相信随着 JDK 的不断完善,更多的工具将具有 API 支持,我们拭目以待。谢谢 谢!谢!