首页 / 软件开发 / JAVA / 使用 Java 6 API分析源码
使用 Java 6 API分析源码2011-07-28Deepa Sobhana您可曾想过像 Checkstyle 或 FindBugs 这样的工具如何执行静态代码分析吗,或者像 NetBeans 或 Eclipse 这样的集成开发环境(Integrated Development Environments IDE)如何执行快速代码修复或 查找在代码中声明的字段的完全引用吗?在许多情况下,IDE 具有自己的 API 来解析源码并生成标准树 结构,称为 抽象语法树(Abstract Syntax Tree AST) 或“解析树”,此树可用于对源码元素的进一步 分析。好消息是,借助于在 Java 中作为 Java Standard Edition 6 发行版的一部分引入的三个新 API ,现在可以实现上述任务以及其他更多任务。可能与需要执行源码分析的 Java 应用程序开发人员相关的 API 有 Java Compiler API (JSR 199)、可插入注解处理(Pluggable Annotation Processing)API (JSR 269) 和 Compiler Tree API。在本文中,我们探讨了其中每个 API 的功能,并继续开发一个简单的演示应用程序,来在作为输入提 供的一套源码文件上验证特定的 Java 编码规则。此实用程序还显示了编码违规消息以及作为输出的违规 源码的位置。考虑一个简单的 Java 类,它覆盖 Object 类的 equals() 方法。要验证的编码规则是实现 equals() 方法的每个类也应该覆盖具有合适签名的 hashcode() 方法。您可以看到下面的 TestClass 类 没有定义 hashcode() 方法,即使它具有 equals() 方法。public class TestClass implements Serializable {
int num;
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
TestClass test = (TestClass) obj;
return num == test.num;
}
}让我们继续借助这三个 API 将此类作为构建过程的一部分进行分析。从代码中调用编译器:Java Compiler API我们全部使用 javac 命令行工具来将 Java 源文件编译为类文件。那么我们为什么需要 API 来编译 Java 文件呢?好的,答案极其简单:正如名称所示,这个新的标准 API 告诉我们从自己的 Java 应用程 序中调用编译器;比如,可以通过编程方式与编译器交互,从而进行应用程序级别服务的编译部分。此 API 的一些典型使用如下。Compiler API 帮助应用服务器最小化部署应用程序的时间,例如,避免了使用外部编译器来编译从 JSP 页面中生成的 servlet 源码的开销IDE 等开发人员工具和代码分析器可以从编辑器或构建工具中调用编译器,从而显著降低编译时间。Java Compiler 类包装在 javax.tools 包中。此包的 ToolProvider 类提供了一个名为 getSystemJavaCompiler() 的方法,此方法返回某个实现了 JavaCompiler 接口的类的实例。此编译器实 例可用于创建一个将执行实际编译的编译任务。然后,要编译的 Java 源文件将传递给此编译任务。为此 ,编译器 API 提供了一个名为 JavaFileManager 的文件管理器抽象,它允许从各种来源中检索 Java 文 件,比如从文件系统、数据库、内存等。在此示例中,我们使用 StandardFileManager,一个基于 java.io.File 的文件管理器。此标准文件管理器可以通过调用 JavaCompiler 的 getStandardFileManager() 方法来获得。上述步骤的代码段如下所示://Get an instance of java compiler
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//Get a new instance of the standard file manager implementation
StandardJavaFileManager fileManager = compiler.
getStandardFileManager(null, null, null);
// Get the list of java file objects, in this case we have only
// one file, TestClass.java
Iterable<? extends JavaFileObject> compilationUnits1 =
fileManager.getJavaFileObjectsFromFiles("TestClass.java");