IDEA插件:FindBugs-- 在Java程序中查找错误

2024-03-23 15:10

本文主要是介绍IDEA插件:FindBugs-- 在Java程序中查找错误,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FindBugs安装

环境要求

FindBugs是一款 静态分析工具,检查程序潜在bug,在bug报告中快速定位到问题的代码上。

FindBugs 运行需要 1.7 或更高版本的 JRE(或 JDK),但是它可以分析从任何版本的 Java 编译的程序,从1.0 到 1.8

IDEA安装FindBugs插件

在IDEA的设置(Settings)中搜索FindBugs-IDEA

 FindBugs使用

注意:安装后需要重启idea

安装好重启,在IEDA下面会有FindBugs-IDEA标致的控制面板

FindBugs-IDEA插件面板按钮说明

 

1 分析选中的 Java 文件(Ctrl+Alt+Shift+F)
2 分析在光标所在的类(Ctrl+Alt+Shift+C)
3 分析选中的包
4 分析选中的模块 (点击时会询问是否同时分析 test 包中的类)
5 分析整个项目 (点击时会询问是否同时分析 test 包中的类)
6 自定义分析的类
7 分析被修改的类 (搭配 SVN,Git 使用) (Alt+Shift+C)
8 分析 changelist 中的类 (搭配 SVN,Git 使用) (Alt+Shift+A)
9 停止分析
10 根据 BUG 类型分组
11 根据类分组
12 根据包分组
13 根据 BUG 严重级别分组

我们是使用 BUG 严重级别进行分组如下图

  • Of Concren 建议, 如果遵循能更好的完善代码
  • Troubling 不好的, 可能会引发不良后果
  • Scary 严重问题, 在某种情况下一定会出现问题
  • Scariest 非常严重, 已经影响到当前程序功能
  • 可以按照严重级别倒序进行修复, 如果时间允许, 可以将 Of Concren 中的问题也一并修复


具体提示的 BUG 进行分析 (黄色编号)


1.Random object created and used only once (Random 对象创建后只使用一次)

该方法每次运行都会创建一个新的 Random 对象, 执行一次后就会被回收. 但是在多线程情况获取随机数方法也能正常使用, 所以可以定义一个 Random 对象常量, 然后使用该常量对象进行方法调用. 能减少创建对象的性能开销

2.Class defines equals() and uses Object.hashCode() (覆写了 equals 方法但是没有覆写 hashCode 方法)

在 Set,Map 中会使用对象的 hashCode 方法, 如果覆写了 equals 方法但是没有覆写 hashCode 方法会导致在 Set,Map 对象中出现问题

3.Inefficient use of keySet iterator instead of entrySet iterator (keySet 迭代器低效, 应该使用 entrySet 进行替换)

如果需要获取 Map 中的 key 和 value, 使用 Map.entrySet() 方法返回 Set<Map.Entry<K, V>> 对象, 然后迭代该 Set, 在使用 Entry 对象获取 key 和 value 更为高效

4.Method ignores return value (方法忽略返回值)

String 对象是不可变的, 当调用 String.trim() 后, 是返回一个新的 String 对象, 不会对调用者的内容进行改动

5.int value cast to float and then passed to Math.round (将 int 值转换为 float,然后传递给 Math.round)

Math.round() 方法只接收 float 和 double 类型, 然后转换为 int 和 long 类型, 如果传递 int 类型, 会先将其转换为 float 类型, 然后再转换为 int 类型, 所以导致该操作返回值与参数内容一致

6.Call to static DateFormat (调用静态的 DateFormat 对象)

DateFormat 对象是线程不安全的, 如果多线程调用同一个 DateFormat 对象会导致结果异常

FindBugs 只是一款静态代码分析工具, 虽然分析大多数的问题, 但是如果希望编写更为健壮的程序, 还需进行更多的测试操作, 切不可认为 FindBugs 没有分析出问题便认为没有问题了

 

FindBugs代码缺陷分类

根据缺陷的性质,大致可以分为下列几类

  • Bad practice  编程的坏习惯

主要是命名问题,比如类名最好以大写开头,字符串不要使用等号不等号进行比较,可能会有异常最好用try-catch包裹的代码,方法有返回值但被忽略等等,这些如果不想改可以直接忽略.

  • Correctness   代码的正确性 这一项应该算是最重要的了 

主要是没有对变量进行不为空判定,在特殊情况可能发生空指针异常.

  • Dodgy code     糟糕的代码

·比如一个double/float被强制转换成int/long可能会导致精度损失,一些接近零的浮点数会被直接截断,事实上我们应该保留. 
在类型转换的时候,我们应该为类型转换提供一个安全的转换方法,因为我们永远不会知道,我们的app在用户手里会发生什么,所以我们要尽可能的去减少这种发生错误的可能.

·比如使用switch的时候没有提供default。

·多余的空检查,就是不可能为空的值,增加了不为空判断,这是没有必要的。属于代码冗余

·不安全的类型转换等等。 
这项太多了,就不一一列举了

  • Experimental  实验
  • Internationalization  国际化
  • Malicious([məˈlɪʃəs] ) code vulnerility 恶意的代码漏洞

听起来很吓人呀,主要是一些属性直接使用public让别的类来获取,建议改为private并为其提供get/set方法

还有一些public的静态字段,可能会被别的包获取之类的. 
这些也需要根据项目具体情况来,个人意见,在有的不重要类,有时直接公开使用属性,可能更为便捷.如果你认为这些不需要修改,完全可以忽略.

  • Multithreaded correctness 多线程问题
  • ·Performance  性能问题

主要是一些无用的代码,比如声明了没有用到的属性等等

根据需要可以进行更改,其中Correctness这个错误使我们重点关注的对象,这里大多是空指针的错误,根据提示进行处理。

附:一些常见的错误信息 


Bad practice 代码中的一些坏习惯

  1. Class names should start with an upper case letter 主要包括类名的命名,以大写字母开头 
  2. Method names should start with a lower case letter 方法名以小写字母开头 
  3. Field names should start with a lower case letter 字段名以小写字母开头 
  4. equals()method does not check for null argument equals()方法应该检查非空 
  5. Class defines equals() and uses Object.hashCode() 一个类覆写了equals方法,没有覆写hashCode方法,使用了Object对象的hashCode方法 
  6. Method ignores exceptional return value 方法忽略返回值的异常信息 
  7. Equals method should not assume anything about the type of its argument equals(Object o)方法不能对参数o的类型做任何的假设。比较此对象与指定的对象。当且仅当该参数不为 null,并且是表示与此对象相同的类型的对象时,结果才为 true。 
  8. Comparison of String objects using == or != 用==或者!=去比较String类型的对象 
  9. Method might ignore exception 方法可能忽略异常 
  10. Method invokes System.exit() 在方法中调用System.exit(…)语句,考虑用RuntimeException来代替 
  11. Method ignores result of InputStream.read() InputStream.read方法忽略返回的多个字符,如果对结果没有检查就没法正确处理用户读取少量字符请求的情况。


Dodgy code 糟糕的代码

  1. Switch statement found where default case is missing Switch没有默认情况下执行的case语句 
  2. Switch statement found where one case falls through to the next case Switch语句中一个分支执行后又执行了下一个分支。通常case后面要跟break 或者return语句来跳出。 
  3. Dead store to local variable 该指令为局部变量赋值,但在其后的没有对她做任何使用。通常,这表明一个错误,因为值从未使用过。 
  4. Write to static field from instance method 在实例方法写入静态字段 
  5. Redundant nullcheck of value known to be non-null 方法中对不为空的值进行为空的判断。 
  6. Method uses the same code for two branches 此方法使用相同的代码,以实现两个有条件的分支。检查以确保这是不是一个编码错误 
  7. Exception is caught when Exception is not thrown 在try/catch块中捕获异常,但是异常没有在try语句中抛出而RuntimeException又没有明确的被捕获 
  8. Integral division result cast to double or float 整形数除法强制转换为double或者float类型。 
  9. Possible null pointer dereference due to return value of called method 方法的返回值没有进行是否为空的检查就重新赋值,这样可能会出现空指针异常。 
  10. Useless object created 对象创建了并没有用 
  11. Unread public/protected field 没有用到的字段 
  12. Internationalization 关于代码国际化相关方面的
  13. Consider using Locale parameterized version of invoked method 
  14. 使用平台默认的编码格式对字符串进行大小写转换,这可能导致国际字符的转换不当。使用以下方式对字符进行转换 


Performance 关于代码性能相关方面的

  1. Boxing/unboxing to parse a primitive 类型转换 比如字符串转换成int 应该使用Integer.parseInt(“”) 代替Integer.valueOf(“”) 
  2. Method concatenates string using + in aloop 
  3. 每次循环里的字符串+连接,都会新产生一个string对象,在java中,新建一个对象的代价是很昂贵的,特别是在循环语句中,效率较低 -----解决办法---:使用StringBuffer或者StringBuilder重用对象。 
  4. Private method is never called 私有方法没有被调用 
  5. Explicit garbage collection;extremely dubious except in benchmarking code 
  6. 在代码中显式的调用垃圾回收命名,这样做并不能起作用。在过去,有人在关闭操作或者finalize方法中调用垃圾回收方法导致了很多的性能浪费。这样大规模回收对象时会造成处理器运行缓慢。 
  7. Unread field:should this field be static? 没有用到的static 字段 
  8. should be a static inner class 此内部类应该使用static修饰 


Experimental

  1. Method may fail to clean up stream or resource on checked exception ----------这种方法可能无法清除(关闭,处置)一个流,数据库对象,或其他资源需要一个明确的清理行动---------解决方法:流的关闭都写在finally里面 
  2. Malicious code vulnerability 关于恶意破坏代码相关方面的
  3. May expose internal representation by incorporating reference to mutable object 
  4. 此代码把外部可变对象引用存储到对象的内部表示。如果实例受到不信任的代码的访问和没有检查的变化危及对象和重要属性的安全。存储一个对象的副本,在很多情况下是更好的办法。 
  5. Field isn’t final but should be 此字段前应该加final 
  6. Field isn’t final and can’t be protected from malicious code 此字段前应该加final 
  7. Field should be package protected 
  8. 一个静态字段是可以被恶意代码或其他的包访问修改。可以把这种类型的字段声明为final类型的以防止这种错误。 
  9. Multithreaded correctness 关于代码正确性相关方面的
  10. Static DateFormat DateFormat 在多线程中本身就是不安全的,如果在线程范围中共享一个DateFormat的实例而不使用一个同步的方法在应用中就会出现一些奇怪的行为。 
  11. Call to static DateFormat DateFormats多线程使用本事就是不安全的,改进方法:需要创建多实例或线程同步 
  12. Correctness 关于代码正确性相关方面的
  13. Nullcheck of value previously dereferenced 此代码之前废弃null值检查。解决办法 进行null检查 
  14. Possible null pointer dereference 可能为null 
  15. Null pointer dereference 对象赋为null值后 没有被重新赋值 
  16. Possible null pointer dereference in method on exception path 在异常null值处理分支调用的方法上,可能存在对象去除引用操作 
  17. value is null and guaranteed to be dereferenced on exception path exception分支上,存在引用一个null对象的方法,引发空指针异常。 
  18. Self comparison of value with itself 方法中对一个局部变量自身进行比较运算,并可说明错误或逻辑错误。请确保您是比较正确的事情。 
  19. An apparent infinite recursive loop 明显的无限迭代循环,将导致堆栈溢出.
     

这篇关于IDEA插件:FindBugs-- 在Java程序中查找错误的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/838707

相关文章

使用Python创建一个功能完整的Windows风格计算器程序

《使用Python创建一个功能完整的Windows风格计算器程序》:本文主要介绍如何使用Python和Tkinter创建一个功能完整的Windows风格计算器程序,包括基本运算、高级科学计算(如三... 目录python实现Windows系统计算器程序(含高级功能)1. 使用Tkinter实现基础计算器2.

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.