`
brandNewUser
  • 浏览: 455433 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

PMD分析源码过程简介

阅读更多

1.    PMD简介

PMD是一款采用BSD协议发布的Java程序代码检查工具。该工具可以做到检查Java代码中是否含有未使用的变量、是否含有空的抓取块、是否含有不必要的对象等。该软件功能强大,扫描效率高,是Java程序员debug的好帮手。

PMD是扫描 Java 源码并查找以下潜在问题:

空捕捉块(catch block

  • 从未用过的参数
  • if声明
  • 重复的导入声明
  • 从未用过的私有方法
  • 孤立的类
  • 短型或长型变量及方法名

PMD 具有下列软件的插件:JEdit, JBuilder, NetBeans/Sun ONE Studio, IntelliJ IDEA, TextPad, Maven, Ant, Eclipse, Gel, Emacs

1.1          PMD 的含义

坦率地说,我们其实也不知道PMD的真正意义所在 (我们只是认为这三个字母拼在一起较为好听) 。但是,我们提出了计算行业的几种解释以供参考。

PMD:

  • Pretty Much Done  (几乎无所不能)
  • Project Mess Detector  (项目故障探测器)
  • Project Monitoring Directives  (项目监视器)
  • Protein Mutant Database  (基因突变数据库)
  • Project Meets Deadline  (项目到期)
  • Programming Mistake Detector  (程序错误检测器)
  • Pounds Mistakes Dead  (彻底纠错)
  • PMD Meaning Discovery  PMD含义探索)

1.2          PMD运行机制

PMD 根据规则核对源码并产生一个报告。具体如下:

  • 有文件名和RuleSet传入PMD
  • PMD将通过该文件的InputStream传递给由JavaCC-生成的解析器;
  • PMD 从解析器取得指向抽象语法树(AST)的引用;
  • RuleSet 中的每个规则都遍历AST 并检查错误;
  • 报告内容包括RuleViolations以及符合XML HTML 或其它格式的代码/文件;

1.3          PMD用法

PMD之后有几个选项:

Generate reports:生成报告,生成在你的工程目录下的reports里;

Clear violation reviews

Find suspect Cut And Paste..:是检查指种后缀的文件。如JAVAJSP等;

Check Code With PMD:就是检查代码。

做好以上步骤以后就会在项目中静态的检测你每一行的代码,如果有不符合要求的会出现警告和错误信息。

2.    集成PMD至规则插件

NC规则检查工具原来的代码检查使用的是JavaParser,但是JavaParser毕竟功能上比较弱,能够分析出来的结果不够全面,而且最近一段时间没有更新,仅支持Java1.5

因此,考虑到有些部门提出的规则对代码检查要求比较复杂,JavaParser很难进行编程处理,考虑集成PMD中的源码,改造其API入口方法,使其能够在实际的规则中使用,并能够以PMD规则的方式对其进行扩展。

集成后的PMD功能包括:

l  仅保留支持Java1.7代码的检查,将其他文件(xmlhtmljspcpp等)的支持抛弃;

l  去除用于代码检查时进行性能测试的Benchmark功能;

l  仍然保持了整个规则执行的整理流程,去掉了原有规则集合(RuleSetFactory, RuleSet)的概念,仅支持单个规则的检查;

l  保留了PMD中原有的各类规则;

l  去除了用于生成报告的过程;

 

最后进行规则检查只需要执行SourceCodeProcessor中的如下方法即可:

         /**

          * 解析规则文件,得出解析结果上下文

          * @param filePath -源代码文件路径

          * @param rule -要执行的规则实现

          * @return

          * @throws FileNotFoundException

          */

         publicstatic RuleContext parseRule(String filePath, Rule rule) throws FileNotFoundException{

 

         其中,用户需要做的事情就是执行规则检查时,扩展Rule接口,其中扩展部分内容见下节。

         用户使用pmd工具需要事先依赖pmdbundlecom.yonyou.nc.codevalidator.code.pmdadaptor

3.    PMD扩展

在介绍完PMD的使用后,下面重点介绍该如何对PMD进行扩展,如何编写自己的规则用在代码检查上。

 

3.1          规则Rule类结构

 

        

 

规则的最基础接口是net.sourceforge.pmd.Rule,其中有一系列的抽象类,下面主要介绍几个重要的抽象类:

AbstractStatisticJavaRule:顾名思义,该抽象类主要就是用于处理一些统计规则的实现,比如计算方法体中代码行数超出一定范围,过多的方法参数,过长的class文件等。如果用户需要计算一些统计信息,可以从此类中派生。

AbstractJavaRule: 一般的Java源码分析规则都是从本类中继承,包括前面所说的统计规则;当前其中也包括一些包含某些特殊帮助方法的规则抽象类,用户可参考其实现。总之,用户如果没有找到特殊适合的实现类型,那么从该类中继承并实现规则。

 

3.2          Java NodeVisitor访问

PMD中的源码分析与JavaParser大体类似,都是将整个Java文件分析成各种子Node,且Node之间存在着Composite关系,采用访问者模式(Visitor模式,参考设计模式),这样就可以在解析Java文件的时候,选择切入点,关注感兴趣的具体Node实现(后面详细介绍Node的结构)。

 

 

 

 

3.3          Java Node的结构

在进行Java代码检查的时候,经常会使用的便是PMD中提供的JavaNode结构,只有详细了解了JavaNode的结构,才能够有针对性的编写检查代码中特定问题的规则。

编译单元(.java)分析

下面就从最顶层的一个编译单元说起,详细介绍一下JavaNode中的结构,一个编译单元就是对应一个.java文件(其中可能包含多个类,包括内部类)。

 

 

         ASTCompilationUnit包括三个基本部分:ASTPackageDeclaration(包声明),ASTImportDeclaration(引用其他类声明)ASTTypeDeclaration类型声明。

         其中包声明和引用列表声明中引用的类都以ASTName形式存在;

         如果类中包含非内部类,会存在多个ASTTypeDeclaration

类型声明分析

         对于具体的类型声明,包括ASTExtendsList(继承的类,java中只能继承单个)ASTImplementsList(实现的接口,可多个)和ASTClassOrInterfaceBody(实现类或接口体)。

 

 

         当类型中存在着内部类时(不区分静态或非静态内部类),ASTClassOrInterfaceBody中会包含多个ASTClassOrInterfaceBodyDeclaration,其中内部类的子仍然聚合了对应的ASTClassOrInterfaceDeclaration,主类向下延伸,见下文。

具体类型元素分析

具体的类型实现体中,包含下面的内容:

ASTFieldDeclaration:字段声明,其中有着ASTType字段的类型(根据情况分为基本类型ASTPrimaryType和引用类型ASTReferenceType),以及ASTVariableDeclarator字段变量的定义。

ASTConstructorDeclaration:构造方法声明,其中包括ASTFormalParameters构造函数参数和对应ASTBlockStatement构造函数语句

ASTMethodDeclaration:方法声明,包含ASTReturnType返回值定义,ASTMethodDeclarator方法定义(其中可包含多个方法参数),ASTNameList可能抛出的异常列表,ASTBlock方法体。

 

 

         实现AccessNode接口的Node(都是从AbstractJavaAccessNode中继承),其中都有着访问符(modifiers)API,即可以访问该字段或方法声明中修饰符(static, final, private等)。

 

 

         而对于类似字段声明的部门,都存在着一颗类似上图中的结构(ASTFieldDeclaration结构)。

常见方法内语句结构图

下面介绍一下比较常见的方法内语句结构图(do whilefor循环类似,暂不介绍):

try语句

         try语句statement包含ASTBlocktry块中的内容),ASTCatchStatementcatch块中的内容),ASTFinallyStatementfinally语句中的内容),其中catchfinally块递归也包含相应ASTBlockASTBlockStatement

 

        

 

If语句

 

 

解析完成的结构:

         其中,第一个ASTExpression为判断语句,第二个ASTStatementif内部体,第三个ASTStatement中又包含了一个ASTIf语句,此为else子句,以此类推,最后的else嵌入在ASTStatement中。

 

 


 至于其他类型分支,分析过程都比较类似,这里就不一一介绍了。

3.4          规则编写常用的方法

编写规则需要直接从net.sourceforge.pmd.lang.java.rule.AbstractJavaRule中(或其子类)继承,严格遵守Visitor模式(参考设计模式),仅关注需要实现的方法。

可以参考pmd中内置的规则实现,写出自己的规则,内置的规则实现在bundle/com.yonyou.nc.codevalidator.code.pmdadaptor中,net.sourceforge.pmd.lang.java.rule包下,已按照规则的分类和使用情况分成不同的实现包进行管理,并在每个包中都有一个对应的xml文件用于描述本包中的规则意义。

 

 

 

         此外,还有一些常用的方法,用来在规则中使用,没介绍的方法,自己查阅,有问题沟通。

 

String net.sourceforge.pmd.lang.ast.Node.getImage()

在某些类型的节点中,用来获得定义的方法名,变量名,参数名等名称类信息,具体请查看相应的定义;

 

<T> List<T> net.sourceforge.pmd.lang.ast.Node.findDescendantsOfType(Class<T> targetType)

在某个节点上,查找其子节点中是否包含某个特定类型的子节点(递归向下查询)。

 

<T> List<T> net.sourceforge.pmd.lang.ast.AbstractNode.getParentsOfType(Class<T> parentType)

在某个节点上,查找其父节点是否包含某个特定类型(递归向上查询)。

 

Node net.sourceforge.pmd.lang.ast.Node.jjtGetChild(int index)

得到节点的子节点,可通过node.jjtGetNumChildren()获取子节点的数量来协助工作。

 

结束

最后,由于项目中用到了PMD中的分析过程,而剥离掉原有的例如报表生成等功能,抽象出了一个简单可轻易调用的类库及其源码,具体信息请参考github:

https://github.com/clamaa/pmd-adaptor

 

  • 大小: 6.7 KB
  • 大小: 6.5 KB
  • 大小: 60.9 KB
  • 大小: 40.7 KB
  • 大小: 71.1 KB
  • 大小: 42.9 KB
  • 大小: 5.1 KB
  • 大小: 11.6 KB
  • 大小: 4.4 KB
  • 大小: 97.2 KB
分享到:
评论

相关推荐

    PMD对java程序分析实验报告

    PMD分析完成后,会生成XML或HTML格式的报告,列出所有检测到的问题。报告包含问题的严重级别、规则名称、代码位置以及建议的改进措施。开发者应根据报告内容逐一审查并修复这些问题。 **六、自定义规则集** 除了...

    PMD用于根据源代码分析查找不良的编程习惯

    总的来说,PMD是Java开发过程中不可或缺的工具之一,通过它,开发者可以持续改进代码质量,减少潜在的bug,提升团队的开发效率,并且保持代码的一致性和可读性。使用PMD进行代码审查,可以培养良好的编程习惯,是每...

    pmd,.zip

    你可以查看源代码来了解其内部实现,阅读文档以熟悉如何使用和配置PMD,运行测试用例以验证其功能,甚至可以修改源码来添加新的规则或者改进现有功能。 总的来说,PMD是开发者提高代码质量、减少bug的有效工具,也...

    idea plugin pmd

    “源码”标签表明PMD插件主要针对的是代码质量检查,它能分析项目中的源代码,找出不符合最佳实践或可能导致问题的部分。而“工具”标签则意味着PMD是开发过程中的一种辅助工具,能够提高开发效率,减少因低级错误...

    sonar-pmd-p3c.zip

    4. **运行代码分析**:通过SonarQube的Scanner,对项目源码进行扫描。这将生成一个报告,列出所有检测到的问题和建议。 5. **查看和修复问题**:在SonarQube的Web界面中,你可以查看每个问题的详细信息,包括严重性...

    Gradle平台集成静态代码检查(findbugs,pmd,checkstyle)

    - **pmd任务配置**:虽然内容片段中没有具体描述pmd任务的配置,但可以推理出,必须在build.gradle文件中添加PMD插件并定义相应的pmd任务来执行PMD分析。 **5. Jenkins集成** - **Jenkins Job配置**:通过Jenkins...

    eclipse 插件fatjar、findbug、pmd

    它通过分析字节码而非源代码,因此即使没有源码也能工作。FindBugs能检测出多种类型的错误,如空指针异常、资源未关闭、并发问题等,有助于提高代码质量和稳定性。在Eclipse中集成FindBugs后,开发者可以实时查看...

    CodeRefactor-源码.rar

    通过对"CodeRefactor-源码.zip"的深入研究,开发者可以学习到如何有效地分析源码,发现并解决潜在问题,以及如何运用重构技术优化代码结构,提升软件质量。这份资料对于提升个人编程技能和团队协作效率具有极高的...

    检测源码.zip

    3. **静态代码分析**:这是一种在不运行代码的情况下分析源码的技术,用于发现潜在的缺陷、安全漏洞和性能瓶颈。例如,PMD、FindBugs和ESLint等工具可以帮助开发者在早期阶段识别问题。 4. **单元测试**:源码检测...

    代码静态检查 PMD findBugs checkStyle

    在软件开发过程中,确保代码质量是至关重要的。代码静态检查工具正是为了这一目的而存在的,它们可以帮助开发者在程序运行之前发现潜在的错误和不规范的编程习惯。在本篇文章中,我们将聚焦三个知名的代码静态检查...

    java源码剖析-Gagawa:该项目的目的是在名为“Gagawa”的开源项目上使用静态和动态分析。静态分析是使用诸如Findbugs,PMD

    在软件开发过程中,无论是为了提高代码质量、查找潜在的错误,还是为了提升性能,源码分析都是至关重要的步骤。Gagawa项目将这一过程带到Java开发领域,它结合了静态分析和动态分析两种方法,以全面了解代码的行为和...

    sonar-p3c-pmd:声纳P3C PMD插件

    声纳P3C PMD插件是专为Java开发人员设计的一款工具,它整合了SonarQube和P3C(Alibaba Coding Guidelines)的规则,旨在帮助开发者在编码过程中遵循阿里巴巴的编程规范,提高代码质量和可维护性。PMD是著名的源代码...

    双层规划模型的遗传算法求解的Matlab源码.doc

    Matlab 是一种高级的编程语言,广泛应用于科学计算、数据分析和机器学习等领域。该源码使用 Matlab 语言实现了一个基于遗传算法的双层规划模型,能够高效地解决复杂的优化问题。 知识点4:种群初始化 种群初始化是...

    基于Java的实例源码-软件度量源码.zip

    11. **设计模式的应用**:识别和分析源码中使用的设计模式,如单例、工厂、观察者等,可以反映代码的可维护性和可扩展性。 12. **性能度量**:通过JProfiler、VisualVM等工具监控内存使用、CPU消耗、线程状态等,以...

    计算机软件-商业源码-软件度量方面的源码.zip

    这个压缩包"计算机软件-商业源码-软件度量方面的源码.zip"显然包含了与软件度量相关的源代码,这可能是用于分析、监控和优化软件开发过程的工具或算法实现。下面,我们将深入探讨软件度量的重要性和相关知识点。 ...

    java 扫描器源码

    - **静态代码分析**:用于检查代码风格、潜在错误和安全问题的工具,如PMD、Checkstyle等,依赖扫描器来理解代码结构。 - **重构工具**:在进行大规模代码改造时,扫描器可以帮助快速定位和替换特定模式。 - **代码...

    source_analysis

    - **安全评估**:通过分析源码,可以识别潜在的安全漏洞,预防黑客攻击。 - **性能优化**:找出性能瓶颈,进行代码优化,提升系统运行效率。 - **维护与升级**:理解代码结构便于后期的维护和功能扩展。 - **...

    dpdk-源码学习。。。

    1. **初始化过程**:DPDK的启动涉及EAL(基础运行时环境)初始化,它负责分配大页内存、识别和绑定CPU核心到特定的网络端口,以及配置中断处理等。 2. **内存管理**:DPDK使用大页内存来减少内存分配的开销,提高...

    《重构-改善既有代码的设计》电子书以及总结的书中源码

    《重构-改善既有代码的设计》是一本由Martin Fowler所著的经典IT著作,专注于软件开发中的重构实践和技术。这本书深入探讨了如何通过一...通过阅读和分析这些源码,开发者可以进一步提升自己的重构能力,提高代码质量。

Global site tag (gtag.js) - Google Analytics