FindBugs 规则整理:CORRECTNESS

UWF_NULL_FIELD

  • 翻译
    Field only ever set to null: …
    All writes to this field are of the constant value null, and thus all reads of the field will return null. Check for errors, or remove it if it is useless.
    某个域的值一直都为null,导致所有读取到的该域的值也都是null,检查该域是否存在异常,或者移除这个无用的域
  • 原因
    在某个类里面我们定义了一个私有的成员变量,但是这个成员变量在实例范围内没有得到任何的初始化(采用默认的构造方法),始终为null,所以在实例范围内使用该成员变量时,如果不先对其进行初始化操作或者无意识的行为忘了初始化操作,那肯定是要报空指针异常
  • 解决方案
    对该变量进行正确的赋值或者移除

RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE

  • 翻译
    Nullcheck of form at line .. of value previously dereferenced in …
    A value is checked here to see whether it is null, but this value can’t be null because it was previously dereferenced and if it were null a null pointer exception would have occurred at the earlier dereference. Essentially, this code and the previous dereference disagree as to whether this value is allowed to be null. Either the check is redundant or the previous dereference is erroneous.

    某个值虽然在某处有被判断是否为null,但是这个值在该处并不可以为null,因为这个值被提前引用了,如果他有可能是null,在被引用的时候就会产生空指针异常,所以这里的判断也就是多余的,而在该判断之前的引用也可能是错误的。
  • 原因
    判断某个值是否为null的时机错误
  • 解决方案
    修改判断时机等,视具体情况而定

NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH

  • 翻译
    .. is null guaranteed to be dereferenced in … on exception path
    There is a statement or branch on an exception path that if executed guarantees that a value is null at this point, and that value that is guaranteed to be dereferenced (except on forward paths involving runtime exceptions).

    在某个异常发生时候某个值将会被置为null,而该null值会被引用
  • 原因
    比如我们在finally中调用了一个在异常发生时则无法正常初始化的对象,这时候就可能产生空指针等异常
  • 解决方案
    判断每个分支中所引用的值在各种情况下是否符合预期,避免产生异常

NP_NULL_ON_SOME_PATH_EXCEPTION

  • 翻译
    Possible null pointer dereference of .. in … on exception path
    A reference value which is null on some exception control path is dereferenced here. This may lead to a NullPointerException when the code is executed. Note that because FindBugs currently does not prune infeasible exception paths, this may be a false warning.
    Also note that FindBugs considers the default case of a switch statement to be an exception path, since the default case is often infeasible.

    因为某些异常路径的发生导致部分对象无法正常初始化,但后续该对象仍会被调用从而产生空指针异常。由于FindBgus无法去除不会执行的异常路径,所以这也可能是一个错误的警告。
  • 原因
    同NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH
  • 解决方案
    同NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH

EC_UNRELATED_TYPES

  • 翻译
    Call to String.equals(Double) in …
    This method calls equals(Object) on two references of different class types with no common subclasses. Therefore, the objects being compared are unlikely to be members of the same class at runtime (unless some application classes were not analyzed, or dynamic class loading can occur at runtime). According to the contract of equals(), objects of different classes should always compare as unequal; therefore, according to the contract defined by java.lang.Object.equals(Object), the result of this comparison will always be false at runtime.

    两个不同的类的实例通过equals方法,通常情况下都会判断为非相同对象,其返回值也将始终为false。
  • 原因
    如第一行所说,调用string的equals方法比较double类型,永远都会返回false,如果把这个作为逻辑判断是没有意义的
  • 解决方案
    去除这种无意义的判断

DMI_INVOKING_TOSTRING_ON_ARRAY

  • 翻译
    Invocation of toString on … in …
    The code invokes toString on an array, which will generate a fairly useless result such as [C@16f0472. Consider using Arrays.toString to convert the array into a readable String that gives the contents of the array. See Programming Puzzlers, chapter 3, puzzle 12.

    在一个array数组上调用toString将返回如C@16f0472等无意义的结果,可以使用Arrays.toString方法来将数组转换为可读的字符串。
  • 原因
    大多数这个问题出在直接打印某个数组是否为空,而FindBugs不知道此处只是log日志,这种直接打印的方法会默认调用对象的toString方法,输出对象的内存地址,也不排除其他情况。
  • 解决方案
    如果是日志可以选择不处理或者隐藏日志,其他情况则视具体情况而定。

UWF_UNWRITTEN_FIELD

  • 翻译
    Unwritten field: …
    This field is never written. All reads of it will return the default value. Check for errors (should it have been initialized?), or remove it if it is useless.

    某个域没有被赋值过,所有对这个变量的读取都会获得默认值,检查该变量是否存在异常,或者移除这个无用的变量
  • 原因
    变量只有默认值,后续没有再进行任何赋值过
  • 解决方案
    判断是否存在使用上的异常,或者抽取为final常量等,视情况而定

IL_INFINITE_RECURSIVE_LOOP

  • 翻译
    There is an apparent infinite recursive loop in …
    This method unconditionally invokes itself. This would seem to indicate an infinite recursive loop that will result in a stack overflow.

    在某处存在死循环。
  • 原因
    如无跳出条件的递归等造成的死循环
  • 解决方案
    修改出现死循环的代码

FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER

Doomed test for equality to NaN
This code checks to see if a floating point value is equal to the special Not A Number value (e.g., if (x == Double.NaN)). However, because of the special semantics of NaN, no value is equal to Nan, including NaN. Thus, x == Double.NaN always evaluates to false. To check to see if a value contained in x is the special Not A Number value, use Double.isNaN(x) (or Float.isNaN(x) if x is floating point precision).

判断是否与NaN相等,但是并不会有值与NaN相等,所以这个判断永远返回false

BC_IMPOSSIBLE_CAST

Impossible cast
不可能的类转换,执行时会抛出ClassCastException

BC_IMPOSSIBLE_DOWNCAST

Impossible downcast
父类在向下进行类型转换时抛出ClassCastException

BC_IMPOSSIBLE_DOWNCAST_OF_TOARRAY

  • 翻译
    This code is casting the result of calling toArray() on a collection to a type more specific than Object[], as in:
    String[] getAsArray(Collection c) {
    return (String[]) c.toArray();
    }
    This will usually fail by throwing a ClassCastException. The toArray() of almost all collections return an Object[]. They can’t really do anything else, since the Collection object has no reference to the declared generic type of the collection.
    The correct way to do get an array of a specific type from a collection is to use c.toArray(new String[]); or c.toArray(new String[c.size()]); (the latter is slightly more efficient).

    某段代码调用Collection.toArray方法获得一组对Object数组更具体的对象数组,这通常会导致ClassCastException。toArray方法大多数集合会返回Object[],它们不能做其他实际的事情,因为集合对象没有声明泛型类型的引用
  • 原因
    集合转换为数组元素时发生的类转换错误。
  • 解决方案
    使用Collection.toArray(new String[]) 或者Collection.toArray(new String[Collection.size()]) 转换

BC_IMPOSSIBLE_INSTANCEOF

Instanceof will always return false
采用instaneof方法进行比较时总是返回false。前提是保证它不是由于某些逻辑错误造成的。

BIT_AND

Incompatible bit masks
错误的使用&位操作符,例如(e & C)

BIT_AND_ZZ

Check to see if ((…) & 0) == 0
检查恒等的逻辑错误

BIT_IOR

Incompatible bit masks
错误的使用|位操作符,例如(e | C)

BIT_SIGNED_CHECK_HIGH_BIT

Check for sign of bitwise operation
检查逻辑运算符操作返回的标识。例如((event.detail & SWT.SELECTED) > 0),建议采用 !=0 代替 >0

BOA_BADLY_OVERRIDDEN_ADAPTER

Class overrides a method implemented in super class Adapter wrongly
子类错误的覆写父类中用于适配监听其他事件的方法,从而导致当触发条件发生时不能被监听者调用

BX_UNBOXED_AND_COERCED_FOR_TERNARY_OPERATOR

Primitive value is unboxed and coerced for ternary operator
在三元运算符操作时如果没有对值进行封装或者类型转换。例如:b ? e1 : e2

DLS_DEAD_STORE_OF_CLASS_LITERAL

Dead store of class literal
以类的字面名称方式为一个字段赋值后再也没有去使用它,在1.4jdk中它会自动调用静态的初始化方法,而在jdk1.5中却不会去执行。

DLS_OVERWRITTEN_INCREMENT

Overwritten increment
覆写增量增加错误i = i++

DMI_BAD_MONTH

Bad constant value for month
表示月份的错误常量值

DMI_COLLECTIONS_SHOULD_NOT_CONTAIN_THEMSELVES

Collections should not contain themselves
集合不应该包含他们自己本身。

DMI_INVOKING_HASHCODE_ON_ARRAY

Invocation of hashCode on an array
在数组上调用了hashCode

DMI_LONG_BITS_TO_DOUBLE_INVOKED_ON_INT

Double.longBitsToDouble invoked on an int
在int上调用了Double.longBitsToDouble

DMI_VACUOUS_SELF_COLLECTION_CALL

Vacuous call to collections
集合的调用不能被感知。例如c.containsAll(c)总是返回true,而c.retainAll(c)的返回值不能被感知。

DMI_ANNOTATION_IS_NOT_VISIBLE_TO_REFLECTION

Can’t use reflection to check for presence of annotation without runtime retention
不能使用反射检测没有标记为runtime rentention的注解的存在

DMI_VACUOUS_CALL_TO_EASYMOCK_METHOD

Useless/vacuous call to EasyMock method
EasyMock方法的无用/空调用

EC_ARRAY_AND_NONARRAY

equals() used to compare array and nonarray
数组对象使用equals方法和非数组对象进行比较。即使比较的双方都是数组对象也不应该使用equals方法,而应该比较它们的内容是否相等使用java.util.Arrays.equals(Object[], Object[]);
使用指针比较不同的类型

EC_INCOMPATIBLE_ARRAY_COMPARE

equals(…) used to compare incompatible arrays
使用equls方法去比较类型不相同的数组。例如:String[] and StringBuffer[], or String[] and int[]

EC_NULL_ARG

Call to equals() with null argument
调用equals的对象为null

EC_UNRELATED_CLASS_AND_INTERFACE

Call to equals() comparing unrelated class and interface
使用equals方法比较不相关的类和接口

EC_UNRELATED_INTERFACES

Call to equals() comparing different interface types
调用equals方法比较不同类型的接口

EC_UNRELATED_TYPES_USING_POINTER_EQUALITY

Using pointer equality to compare different types
使用指针比较不同的类型

EQ_ALWAYS_FALSE

equals method always returns false
使用equals方法返回值总是false

EQ_ALWAYS_TRUE

equals method always returns true
equals方法返回值总是true

EQ_COMPARING_CLASS_NAMES

equals method compares class names rather than class objects
equals方法比较类名而不是比较类

EQ_DONT_DEFINE_EQUALS_FOR_ENUM

Covariant equals() method defined for enum
为枚举类型定义了equals()方法

EQ_OTHER_NO_OBJECT

equals() method defined that doesn’t override equals(Object)
定义equals()方法,但是没有覆盖equals(Object)

EQ_OTHER_USE_OBJECT

equals() method defined that doesn’t override Object.equals(Object)
定义equals()方法,但是没有覆盖Object.equals(Object)

EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC

equals method overrides equals in superclass and may not be symmetric
equals方法覆盖了父类的equals可能功能不符

EQ_SELF_USE_OBJECT

Covariant equals() method defined, Object.equals(Object) inherited
类中定义了一组equals方法,但是都是继承的java.lang.Object class中的equals(Object)方法

VA_FORMAT_STRING_BAD_ARGUMENT

Format string placeholder incompatible with passed argument
格式化字符串占位符与传入的参数不匹配

VA_FORMAT_STRING_BAD_CONVERSION

The type of a supplied argument doesn’t match format specifier
指定的格式字符串和参数类型不匹配,例如:String.format(“%d”, “1”)

VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED

MessageFormat supplied where printf style format expected
需要使用printf样式时却使用了MessageFormat,从而引起格式化结果出错

VA_FORMAT_STRING_EXTRA_ARGUMENTS_PASSED

More arguments are passed than are actually used in the format string
使用字符串格式化时传递了多余的参数

VA_FORMAT_STRING_ILLEGAL

Illegal format string
格式化String对象语句错误

VA_FORMAT_STRING_MISSING_ARGUMENT

Format string references missing argument
String的format操作缺少必要的参数。

VA_FORMAT_STRING_NO_PREVIOUS_ARGUMENT

No previous argument for format string
格式字符串定义错误,例如:formatter.format(“%<s %s”, “a”, “b”); 抛出MissingFormatArgumentException异常

GC_UNRELATED_TYPES

No relationship between generic parameter and method argument
泛型参数与方法参数没有相互关系

HE_SIGNATURE_DECLARES_HASHING_OF_UNHASHABLE_CLASS

Signature declares use of unhashable class in hashed construct
在哈希构造中声明了无法使用哈希算法的类

HE_USE_OF_UNHASHABLE_CLASS

Use of class without a hashCode() method in a hashed data structure
在哈希数据结构中使用的类没有定义hashCode()方法

ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL

integral value cast to double and then passed to Math.ceil
integral的值转换为double后使用了Math.ceil方法

ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND

int value cast to float and then passed to Math.round
int 类型的值转换为float类型之后调用了Math.round方法

IJU_ASSERT_METHOD_INVOKED_FROM_RUN_METHOD

JUnit assertion in run method will not be noticed by JUnit
在JUnit中的断言在run方法中不会被告知

IJU_BAD_SUITE_METHOD

TestCase declares a bad suite method
在一个JUnit类中声明的一个suite()方法必须声明为 public static junit.framework.Test suite() 或者 public static junit.framework.TestSuite suite() 的形式。

IL_CONTAINER_ADDED_TO_ITSELF

A collection is added to itself
集合本身作为add方法的参数,这样会引起内存溢出。

IL_INFINITE_LOOP

An apparent infinite loop
无法跳出的递归方法引起的死循环

IM_MULTIPLYING_RESULT_OF_IREM

Integer multiply of result of integer remainder
和整数余数进行乘法运算。例如:i % 60 1000 是进行(i % 60) 1000运算而不是 i % (60 * 1000)

INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE

Bad comparison of nonnegative value with negative constant
错误地比较非负数与负数

INT_BAD_COMPARISON_WITH_SIGNED_BYTE

Bad comparison of signed byte
比较有符合数,要先把有符号数转换为无符合数再进行比较

IO_APPENDING_TO_OBJECT_OUTPUT_STREAM

Doomed attempt to append to an object output stream
试图在对象的输出流处添加元素,如果你希望能够添加进一个对象的输出流中,那么必须保证对象的输出流处于打开状态。

IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN

A parameter is dead upon entry to a method but overwritten
传入参数的值没有被使用,但是对传入值进行了修改,并返回给了调用者

MF_CLASS_MASKS_FIELD

Class defines field that masks a superclass field
子类中定义了和父类中同名的字段。在调用时会出错

MF_METHOD_MASKS_FIELD

Method defines a variable that obscures a field
在方法中定义的局部变量和类变量或者父类变量同名,从而引起字段混淆。

NP_ALWAYS_NULL

Null pointer dereference
对象赋为null值后 没有被重新赋值

NP_ALWAYS_NULL_EXCEPTION

Null pointer dereference in method on exception path
方法的异常路径中引用了空指针

NP_ARGUMENT_MIGHT_BE_NULL

Method does not check for null argument
方法没有判断参数是否为空

NP_CLOSING_NULL

close() invoked on a value that is always null
一个为空的对象调用close方法

NP_GUARANTEED_DEREF

Null value is guaranteed to be dereferenced
存在一定会被调用的null对象

NP_NONNULL_PARAM_VIOLATION

Method call passes null to a nonnull parameter
方法中为null的参数没有被重新赋值

NP_NONNULL_RETURN_VIOLATION

Method may return null, but is declared @NonNull
方法声明了返回值不能为空,但是方法中有可能返回null

NP_NULL_INSTANCEOF

A known null value is checked to see if it is an instance of a type
一个已知的null值被用来判断它是否是一个类型的实例

NP_NULL_ON_SOME_PATH

Possible null pointer dereference
可能出现空指针引用

NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS

method call passes null for nonnull parameter
方法参数中声明为nonnull类型的参数为null

NP_STORE_INTO_NONNULL_FIELD

Store of null value into field annotated NonNull
一个已经声明为不能为null值的属性被赋值为null。

NM_BAD_EQUAL

Class defines equal(Object); should it be equals(Object)?
类中定义了一个equal方法但是却不是覆写的Object对象的equals方法

NM_LCASE_HASHCODE

Class defines hashcode(); should it be hashCode()?
类中定义了一个hashCode方法但是却不是覆写的Object中的hashCode方法

NM_LCASE_TOSTRING

Class defines tostring(); should it be toString()?
类中定义了一个toString方法但是却不是覆写的Object中的toString方法

NM_METHOD_CONSTRUCTOR_CONFUSION

Apparent method/constructor confusion
构造方法定义混乱

NM_VERY_CONFUSING

Very confusing method names
混乱的方法命名,如getName和getname方法同时出现的时候

NM_WRONG_PACKAGE

Method doesn’t override method in superclass due to wrong package for parameter
因为包名不正确所以没能正确覆盖父类的方法

QBA_QUESTIONABLE_BOOLEAN_ASSIGNMENT

Method assigns boolean literal in boolean expression
在if或者while表达式中使用boolean类型的值时应该使用==去判断,而不是采用=操作

RC_REF_COMPARISON

Suspicious reference comparison
比较两个对象值是否相等时应该采用equals方法,而不是==方法

RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION

Invalid syntax for regular expression
对正则表达式使用了错误的语法,会抛出未经检查的异常

RE_CANT_USE_FILE_SEPARATOR_AS_REGULAR_EXPRESSION

File.separator used for regular expression
在正则表达式中使用了错误的文件分隔符,在windows系统中正则表达式不会匹配’\’而应该使用’\\’

RV_01_TO_INT

Random value from 0 to 1 is coerced to the integer 0
从0到1随机值被强制为整数值0。在强制得到一个整数之前,你可能想得到多个随机值。可以使用Random.nextInt(n)的方法。

RV_ABSOLUTE_VALUE_OF_HASHCODE

Bad attempt to compute absolute value of signed 32-bit hashcode
此代码生成一个哈希码,然后计算该哈希码的绝对值。如果哈希码是Integer.MIN_VALUE的,那么结果将是负数(因为Math.abs(Integer.MIN_VALUE的)== Integer.MIN_VALUE的)。
在2^ 32值之外字符串有一个Integer.MIN_VALUE的hashCode包括“polygenelubricants”,“GydZG_”和“,”DESIGNING WORKHOUSES “。

RV_ABSOLUTE_VALUE_OF_RANDOM_INT

Bad attempt to compute absolute value of signed 32-bit random integer
此代码生成一个随机的符号整数,然后计算该随机整数的绝对值。如果随机数生成数绝对值为Integer.MIN_VALUE的,那么结果将是负数(因为Math.abs(Integer.MIN_VALUE的)== Integer.MIN_VALUE的)。

RV_EXCEPTION_NOT_THROWN

Exception created and dropped rather than thrown
此代码创建一个异常(或错误)的对象,但不会用它做任何事情。

RV_RETURN_VALUE_IGNORED

Method ignores return value
方法忽略了返回值,应该对返回值进行检查

RpC_REPEATED_CONDITIONAL_TEST

Repeated conditional tests
该代码包含对同一个条件试验了两次,两边完全一样例如:(如X == 0 | | x == 0)。可能第二次出现是打算判断别的不同条件(如X == 0 | | y== 0)。

SA_FIELD_DOUBLE_ASSIGNMENT

Double assignment of field
对属性进行双重赋值

SA_FIELD_SELF_ASSIGNMENT

Self assignment of field
属性自身赋值

SA_FIELD_SELF_COMPARISON

Self comparison of field with itself
属性自己与自己进行了比较

SA_LOCAL_SELF_COMPARISON

Self comparison of value with itself
自己和自己的值比较

SA_LOCAL_SELF_COMPUTATION

Nonsensical self computation involving a variable (e.g., x & x)
此方法对同一变量执行了无意义的计算(如x&x或x-x)操作。由于计算的性质,这一行动似乎没有意义,并可能表明错误或逻辑错误。

SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH

Dead store due to switch statement fall through
在swtich中先前的case值因为swtich执行失败而被覆写,这就像是忘记使用break推出或者没有使用return语句放回先前的值一样。

SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH_TO_THROW

Dead store due to switch statement fall through to throw
在swtich中因为出现异常而忽略了对case值的保存。

SIC_THREADLOCAL_DEADLY_EMBRACE

Deadly embrace of non-static inner class and thread local
如果线程包含对一个内部类实例的引用,那么内外实例的实例都可以被获取,这样就不具备垃圾会回收的资格。

SIO_SUPERFLUOUS_INSTANCEOF

Unnecessary type check done using instanceof operator
在进行instanceof操作时进行没有必要的类型检查

STI_INTERRUPTED_ON_CURRENTTHREAD

Unneeded use of currentThread() call, to call interrupted()
此方法调用Thread.currentThread(),只需调用interrupted()方法。由于interrupted()是一个静态方法, Thread.interrupted()更简单易用。

STI_INTERRUPTED_ON_UNKNOWNTHREAD

Thread.interrupted() method invoked on thread instance
调用不是当前线程对象的Thread.interrupted()方法,由于interrupted()方法是静态的,interrupted方法将会调用一个和作者原计划不同的对象。

SE_METHOD_MUST_BE_PRIVATE

Method must be private in order for serialization to work
这个类实现了Serializable接口,并定义自定义序列化的方法/反序列化。但这种方法不能声明为private,否则将被序列化/反序列化的API忽略掉。

SE_READ_RESOLVE_IS_STATIC

The readResolve method must not be declared as a static method.
为使readResolve方法得到序列化机制的识别,不能作为一个静态方法来声明。

UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS

Uncallable method defined in anonymous class
在匿名类中定义了一个既没有覆写超类中方法也不能直接调用的方法,因为在其他类的方法不能直接引用匿名类声明的方法,似乎这种方法不能被调用,这种方法可能只是没有任何作用的代码,但也可能是覆写超类中声明。

UR_UNINIT_READ

Uninitialized read of field in constructor
此构造方法中使用了一个尚未赋值的字段或属性。

UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR

Uninitialized read of field method called from constructor of superclass
父类的构造方法调用未初始化属性的方法

其他文章(持续更新)

FindBugs:简介与使用
FindBugs 规则整理:Bad Practice
FindBugs 规则整理:Style & Dodgy
FindBugs 规则整理:Malicious Code Vulnerability
FindBugs 规则整理:Multithreaded Correctness
FindBugs 规则整理:Security & Experimental
FindBugs 规则整理:Performance
FindBugs 规则整理:Internationalization

引用

整合以下文章过程中发现部分存在翻译错误,已做修正,同时感谢以下文章作者
FindBugs使用备忘录
FindBugs规则整理
详解FindBugs的各项检测器
Findbugs 缺陷详解与英文代号的对照表


版权声明

![Creative Commons BY-NC-ND 4.0 International License](/images/cc.png)

Lam’s Blog by Binghe Lin is licensed under a Creative Commons BY-NC-ND 4.0 International License.
林炳河创作并维护的Lam’s Blog采用创作共用保留署名-非商业-禁止演绎4.0国际许可证

本文首发于Lam’s Blog - Knowledeg as Action,版权所有,侵权必究。

本文永久链接:http://linbinghe.com/2017/b2ff5786.html