FindBugs检测器实现(2)

系统 2178 0

FindBugs 检测器实现(1) 中提到,FindBugs 主要有5类检测器,这篇日志介绍下FindBugs在类、方法、字段结构上的检测器实现。前面提到基于栈和简单的字节码模式要继承OpcodeStackDetector类,并实现sawOpcode方法用来检测每一个字节码。

一般在写检测器之前,我们应该有一个自己想要检测的代码模式,但作为学习,这里使用一些简单的模式作为例子:

  1. 重写了equals函数,却没有重写hashCode函数。
  2. 经hashCode函数拼写为hashcode。

FindBugs在类、方法、字段层面的检测器实现要继承PreorderDetector类,简单介绍些该类:

 

PreorderVisitor

PreorderVisitor 继承了 BetterVisitor,并在 BetterVisitor的基础之上,添加了大量的方法用来从当前访问的类、方法或字段中获取信息,另外该类还提供了一些visitAfter方法,用来实现访问上的次序,在下面的例子中,我们会看到它的作用。像下面的方法 PreorderVisitor 中存在太多,这里就不一一列出,可能有些方法不能直接明了的知道其作用,大多可能是我们还不懂java的一些功能的缘故:

      
        public
      
      
         FieldDescriptor getFieldDescriptor()


      
      
        public
      
      
         MethodDescriptor getMethodDescriptor()


      
      
        public
      
      
         ClassDescriptor getClassDescriptor()


      
      
        public
      
      
         @SlashedClassName  String getClassName()


      
      
        public
      
      
        void
      
      
         visitAfter(Code obj)


      
      
        public
      
      
        void
      
       visitAfter(JavaClass obj)
    

 

来个例子
        
          public
        
        
          class
        
         DemoPlugin 
        
          extends
        
        
           PreorderDetector {

    
        
        
          private
        
        
           BugReporter bugReporter;

    

    
        
        
          public
        
        
           DemoPlugin(BugReporter reporter){

        bugReporter 
        
        =
        
           reporter;

    }



    
        
        
          public
        
        
          boolean
        
        
           hasHashcode;

    
        
        
          public
        
        
          boolean
        
        
           hasEqual;

    
        
        
          public
        
        
           MethodAnnotation equals;

    

    @Override

    
        
        
          public
        
        
          void
        
        
           visit(JavaClass obj){

        System.out.println(
        
        "visit class!!!!!!!!!" +
        
           obj.getClassName());

        hasHashcode 
        
        = 
        
          false
        
        
          ;

        hasEqual 
        
        = 
        
          false
        
        
          ;

        equals 
        
        = 
        
          null
        
        
          ;

    }

    

    @Override

    
        
        
          public
        
        
          void
        
        
           visit(Method me){

        
        
        
          if
        
        (!
        
          me.isPublic())

            
        
        
          return
        
        
          ;

        
        
        
          if
        
        ("equals".equals(me.getName()) && "(Ljava/lang/Object;)Z"
        
          .equals(me.getSignature())){

            hasEqual 
        
        = 
        
          true
        
        
          ;

            System.out.println(
        
        "find equals() method"
        
          );

            equals 
        
        = MethodAnnotation.fromVisitedMethod(
        
          this
        
        
          );

        }

        

        
        
        
          if
        
        ("hashCode".equals(me.getName()) && "()I"
        
          .equals(me.getSignature())){

            hasHashcode 
        
        = 
        
          true
        
        
          ;

            System.out.println(
        
        "find hashCode() method"
        
          );

        }

        

        
        
        
          if
        
        ("hashcode".equals(me.getName()) && "()I"
        
          .equals(me.getSignature())){

            bugReporter.reportBug(
        
        
          new
        
         BugInstance(
        
          this
        
        , "HASHCODE WRONG SPELL"
        
          , NORMAL_PRIORITY).

                    addClass(getDottedClassName()).addMethod(MethodAnnotation.fromVisitedMethod(
        
        
          this
        
        
          )));

        }

    }

    

    @Override

    
        
        
          public
        
        
          void
        
        
           visitAfter(JavaClass obj){

        
        
        
          if
        
        (hasEqual && !
        
          hasHashcode){

            BugInstance instance 
        
        = 
        
          new
        
         BugInstance(
        
          this
        
        , "EQUALS WITHOUT HASHCODE"
        
          , NORMAL_PRIORITY).

                    addClass(getDottedClassName()).addMethod(equals);

            bugReporter.reportBug(instance);

        }

    }

}
        
      

这里我们继承了PreorderDetector,而PreorderDetector继承了PreorderVisitor,是因为BugInstance需要使用Detector进行实例,而PreorderDetector实现了Detector接口。

上面方法我们使用了上个变量hasHashcode,hasEquals和equals,前两个变量用来保存当前访问的类是否存在hashCode和equals方法,第三个变量存放的是方法注释(要在报告bug中,这里先不管)。

上述三个变量每次都在visit(JavaClass obj)方法中进行状态重置,这样才能对所有的类都进行检测。visit(Method me)方法中用来判断是否是equals、hashCode、hashcode方法,并修改相应的状态。如果是hashcode方法,则直接将该bug报告。

visitAfter(JavaClass obj)方法执行时,已经对当前类检测完毕,这样可以判断是否出现equals方法,而没有出现hashCode方法的情况。

将fandbugs.xml和massage.xml加到项目中打包,便能对我们定义的模式进行检测。

以上仅是一个自定义在类、方法、字段层面上的检测器的一般步骤,例子仅是为了说明过程,只要我们熟悉我们想要检测的模式,就能通过上述方法实现。

FindBugs检测器实现(2)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论