天天看點

配置FindBugs和常見FindBugs錯誤

配置FindBugs:

在這裡可以對FindBugs規則等進行詳細設定。

選擇你的項目,右鍵 => Properties => FindBugs =>

配置FindBugs和常見FindBugs錯誤

1 Run Automatically開關

當此項選中後,FindBugs将會在你修改Java類時自動運作,如你設定了Eclipse自動編譯開關後,當你修改完Java檔案儲存,FindBugs就會運作,并将相應的資訊顯示出來。

當此項沒有選中,你隻能每次在需要的時候自己去運作FindBugs來檢查你的代碼。

2 Detector Configuration選擇項

在這裡你可以選擇所要進行檢查的相關的Bug Pattern條目,你可以根據需要選擇或去掉相應的 檢查條件。

配置FindBugs和常見FindBugs錯誤

3 Minimum priority to report選擇項

這個選擇項是讓你選擇哪個級别的資訊進行顯示,有Low、Medium、High三個選擇項可以選擇,很類似于Log4J的級别設定啦。 比如:

你選擇了High選擇項,那麼隻有是High級别的提示資訊才會被顯示。

你選擇了Medium選擇項,那麼隻有是Medium和High級别的提示資訊才會被顯示。

你選擇了Low選擇項,那麼所有級别的提示資訊都會被顯示。

4 Report bug categories選擇項

在這裡是一些顯示Bug分類的選擇:

Malicious code vulnerability關于惡意破壞代碼相關方面的

Correctness關于代碼正确性相關方面的

Internationalization關于代碼國際化相關方面的

Performance關于代碼性能相關方面的

Multithreaded correctness關于代碼多線程正确性相關方面的

另外FindBugs有UI頁面,可以單獨運作。也可以通過Ant以及指令行方式運作。

其它分析工具

除FingBugs靜态分析工具外,還有PMD和Checkstyle,FingBugs、PMD和Checkstyle三個工具各有不同的特點,聯合使用有助于減少誤報錯誤,提高報告的準确率。

這三個工具檢查的側重點各有不同:

工具

 目的

 主要檢查内容

FindBugs

    基于Bug Patterns概念,查找java bytecode中的潛在bug。在目前版本中,它不檢查java源檔案。 主要檢查bytecode中的bug patterns,也允許使用者自定義特定的bug patterns。

 PMD

 檢查java源檔案中的潛在問題。

 主要包括:

  -  空try/catch/finally/switch語句塊

 -       未使用的局部變量、參數和private方法

 -       空if/while語句

 -       過于複雜的表達式,如不必要的if語句等

 -       複雜類

CheckStyle

 檢查java源檔案是否與代碼規範相符

 主要包括

 -       Javadoc注釋

 -       命名規範

 -       Headers

 -       Imports

 -       Size沖突和度量,如過長的方法

 -       Whitespace

-       Modifiers

 -       Blocks

 -       Coding Problems

 -       Class Design

 -       重複代碼

 -       Miscellaneous Checks

 -       Optional Checks

  配套的Bug解釋模式

為了有針對性的使用這個工具,減少bug的誤報,提高使用效率,我們選擇了10個左右的bug模式,下面就是對這10個模式的解釋。

這些bug可能會引起程式的性能或邏輯問題.

需要說明的是,findbugs能檢測的bug pattern遠不僅于此,甚至可以定制自己的探測器,是以,這個文檔會不斷擴充,同時,也歡迎大家不斷探索和分享使用實踐.

大的分類主要包括以下幾種:

Bad practice 不好的習慣
Correctness 代碼的正确性
Dodgy 小問題
Malicious code vulnerability 惡意代碼
Internationalization 國際化問題
Performance 性能問題
Security 安全性問題
Multithreaded currectness 線程問題
Experrimental 實驗性問題

API: http://findbugs.sourceforge.net/api/index.html

技術手冊: http://findbugs.sourceforge.net/manual/index.html

更多請參見官網: http://findbugs.sourceforge.net/bugDescriptions.html

6.1、       ES_COMPARING_PARAMETER_STRING_WITH_EQ

     ES: Comparison of String parameter using == or != (ES_COMPARING_PARAMETER_STRING_WITH_EQ)

This code compares a java.lang.String parameter for reference equality using the == or != operators. Requiring callers to pass only String constants or interned strings to a method is unnecessarily fragile, and rarely leads to measurable performance gains. Consider using the equals(Object) method instead.

     使用 == 或者 != 來比較字元串或interned字元串,不會獲得顯著的性能提升,同時并不可靠,請考慮使用equals()方法。

6.2、       HE_EQUALS_NO_HASHCODE

     HE: Class defines equals() but not hashCode() (HE_EQUALS_NO_HASHCODE)

This class overrides equals(Object), but does not override hashCode().  Therefore, the class may violate the invariant that equal objects must have equal hashcodes.

     類定義了equals()方法但沒有重寫hashCode()方法,這樣違背了相同對象必須具有相同的hashcodes的原則

6.3、       IT_NO_SUCH_ELEMENT

     It: Iterator next() method can't throw NoSuchElement exception (IT_NO_SUCH_ELEMENT)

This class implements the java.util.Iterator interface.  However, its next() method is not capable of throwing java.util.NoSuchElementException.  The next() method should be changed so it throws NoSuchElementException if is called when there are no more elements to return.

     疊代器Iterator無法抛出NoSuchElement異常,類實作了java.util.Iterator接口,但是next()方法無法抛出java.util.NoSuchElementException異常,是以,next()方法應該做如此修改,當被調用時,如果沒有element傳回,則抛出NoSuchElementException異常

6.4、       J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION

     J2EE: Store of non serializable object into HttpSession (J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION)

This code seems to be storing a non-serializable object into an HttpSession. If this session is passivated or migrated, an error will result.

     将沒有實作serializable的對象放到HttpSession中,當這個session被鈍化和遷移時,将會産生錯誤,建議放到HttpSession中的對象都實作serializable接口。

6.5、       ODR_OPEN_DATABASE_RESOURCE

     ODR: Method may fail to close database resource (ODR_OPEN_DATABASE_RESOURCE)

The method creates a database resource (such as a database connection or row set), does not assign it to any fields, pass it to other methods, or return it, and does not appear to close the object on all paths out of the method.  Failure to close database resources on all paths out of a method may result in poor performance, and could cause the application to have problems communicating with the database.

     方法可能未關閉資料庫資源,未關閉資料庫資源将會導緻性能變差,還可能引起應用與伺服器間的通訊問題。

6.6、       OS_OPEN_STREAM

     OS: Method may fail to close stream (OS_OPEN_STREAM)

The method creates an IO stream object, does not assign it to any fields, pass it to other methods that might close it, or return it, and does not appear to close the stream on all paths out of the method.  This may result in a file descriptor leak.  It is generally a good idea to use a finally block to ensure that streams are closed.

     方法可能未關閉stream,方法産生了一個IO流,卻未關閉,将會導緻檔案描繪符的洩漏,建議使用finally block來確定io stream被關閉。

6.7、       DMI_CALLING_NEXT_FROM_HASNEXT

     DMI: hasNext method invokes next (DMI_CALLING_NEXT_FROM_HASNEXT)

The hasNext() method invokes the next() method. This is almost certainly wrong, since the hasNext() method is not supposed to change the state of the iterator, and the next method is supposed to change the state of the iterator.

6.8、       IL_INFINITE_LOOP

     IL: An apparent infinite loop (IL_INFINITE_LOOP)

This loop doesn't seem to have a way to terminate (other than by perhaps throwing an exception).

     明顯的無限循環.

6.9、       IL_INFINITE_RECURSIVE_LOOP

     IL: An apparent infinite recursive loop (IL_INFINITE_RECURSIVE_LOOP)

This method unconditionally invokes itself. This would seem to indicate an infinite recursive loop that will result in a stack overflow.

     明顯的無限疊代循環,将導緻堆棧溢出.

6.10、   WMI_WRONG_MAP_ITERATOR

     WMI: Inefficient use of keySet iterator instead of entrySet iterator (WMI_WRONG_MAP_ITERATOR)

This method accesses the value of a Map entry, using a key that was retrieved from a keySet iterator. It is more efficient to use an iterator on the entrySet of the map, to avoid the Map.get(key) lookup.

     使用了keySet iterator和Map.get(key)來擷取Map值,這種方式效率低,建議使用entrySet的iterator效率更高.

6.11、   IM_BAD_CHECK_FOR_ODD

     IM: Check for oddness that won't work for negative numbers (IM_BAD_CHECK_FOR_ODD)

The code uses x % 2 == 1 to check to see if a value is odd, but this won't work for negative numbers (e.g., (-5) % 2 == -1). If this code is intending to check for oddness, consider using x & 1 == 1, or x % 2 != 0.

     奇偶檢測邏輯,未考慮負數情況.

7.實際項目中Bug類型統計

7.1、       Call to equals() comparing different types

id : EC_UNRELATED_TYPES, type : EC, category : CORRECTNESS 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.

原因分析:

這缺陷的意思是,大部分都是類型永遠不會有這種情況, 比如a為DOUBLE類型是以EQUALS隻比對字元串 if(a.equals())或if(a.quals())這類判斷是根本不會有用的;

示例:if("1".equals(DAOValue.valueofSuccess()))

7.2、       Dead store to local variable 

id: DLS_DEAD_LOCAL_STORE, type: DLS, category: STYLE

This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used.

Note that Sun's javac compiler often generates dead stores for final local variables. Because FindBugs is a bytecode-based tool, there is no easy way to eliminate these false positives.

原因分析:

DLS問題指的是給本地變量賦了一個值,但随後的代碼并沒有用到這個值。

7.3、       Method call passes null for nonnull parameter

id: NP_NULL_PARAM_DEREF, type: NP, category: CORRECTNESS

This method call passes a null value for a nonnull method parameter. Either the parameter is annotated as a parameter that should always be nonnull, or analysis has shown that it will always be dereferenced.

原因分析:對參數為null的情況未作處理。

例如:

配置FindBugs和常見FindBugs錯誤
配置FindBugs和常見FindBugs錯誤

7.4、       Method with Boolean return type returns explicit null  

id: NP_BOOLEAN_RETURN_NULL, type: NP, category: BAD_PRACTICE

A method that returns either Boolean.TRUE, Boolean.FALSE or null is an accident waiting to happen. This method can be invoked as though it returned a value of type boolean, and the compiler will insert automatic unboxing of the Boolean value. If a null value is returned, this will result in a NullPointerException.

原因分析:

方法如果定義為傳回類型Boolean,則可以傳回Boolean.TRUE, Boolean.FALSE or null (如果 return 的是 true or  false, 則AutoBoxing 成 Boolean.TRUE, Boolean.FALSE)。因為JDK 支援 基本類型和裝箱類型的自動轉化, 是以下面的代碼中:

boolean result = test_NP_BOOLEAN_RETURN_NULL();

因為此時test_NP_BOOLEAN_RETURN_NULL() 傳回的是NULL, 是以 JDK 做 automatic unboxing 的操作時, 即調用了 object. booleanValue() 方法時,抛出了空指針。

改成:boolean result = test_NP_BOOLEAN_RETURN_NULL()==null?false:true;

7.5、       No relationship between generic parameter and method argument

id: GC_UNRELATED_TYPES, type: GC, category: CORRECTNESS

This call to a generic collection method contains an argument with an incompatible class from that of the collection's parameter (i.e., the type of the argument is neither a supertype nor a subtype of the corresponding generic type argument). Therefore, it is unlikely that the collection contains any objects that are equal to the method argument used here. Most likely, the wrong value is being passed to the method.

In general, instances of two unrelated classes are not equal. For example, if the Foo and Bar classes are not related by subtyping, then an instance of Foo should not be equal to an instance of Bar. Among other issues, doing so will likely result in an equals method that is not symmetrical. For example, if you define the Foo class so that a Foo can be equal to a String, your equals method isn't symmetrical since a String can only be equal to a String.

In rare cases, people do define nonsymmetrical equals methods and still manage to make their code work. Although none of the APIs document or guarantee it, it is typically the case that if you check if a Collection<String> contains a Foo, the equals method of argument (e.g., the equals method of the Foo class) used to perform the equality checks.

原因分析:調用Collection類中的contains方法比較時,所比較的兩個參數類型不緻;

例如:

配置FindBugs和常見FindBugs錯誤

修改後:

配置FindBugs和常見FindBugs錯誤

7.6、       Null pointer dereference in method on exception path

id: NP_ALWAYS_NULL_EXCEPTION, type: NP, category: CORRECTNESS

A pointer which is null on an exception path is dereferenced here.  This will 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.

原因分析:在異常處理時,調用一個空對象的方法時可能引起空指針異常。

例如:

配置FindBugs和常見FindBugs錯誤

7.7、       Nullcheck of value previously dereferenced

id: RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE, type:RCN, category: CORRECTNESS

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。

例如:

配置FindBugs和常見FindBugs錯誤

7.8、       Possible null pointer dereference

id: NP_NULL_ON_SOME_PATH, type: NP, category: CORRECTNESS

There is a branch of statement that, if executed, guarantees that a null value will be dereferenced, which would generate a NullPointerException when the code is executed. Of course, the problem might be that the branch or statement is infeasible and that the null pointer exception can't ever be executed; deciding that is beyond the ability of FindBugs.

原因分析:可能存在空引用。

例如:

配置FindBugs和常見FindBugs錯誤

7.9、       Possible null pointer dereference in method on exception path

id: NP_NULL_ON_SOME_PATH_EXCEPTION, type: NP, category:CORRECTNESS

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.

原因分析:

代碼調用時, 遇到異常分支, 可能造成一個對象沒有獲得指派依舊保持NULL空指針。 接下來如果對這個對象有引用, 可能造成NullPointerException 空指針異常。

例如:

配置FindBugs和常見FindBugs錯誤

7.10、   Test for floating point equality

id: FE_FLOATING_POINT_EQUALITY, type: FE, category: STYLE

This operation compares two floating point values for equality. Because floating point calculations may involve rounding, calculated float and double values may not be accurate. For values that must be precise, such as monetary values, consider using a fixed-precision type such as BigDecimal. For values that need not be precise, consider comparing for equality within some range, for example: if ( Math.abs(x - y) < .0000001 ). See the Java Language Specification, section 4.2.4.

原因分析:

Float類型的資料比較時,會存在的定的誤內插補點,用!=來比較不是很準确,建議比較兩個數的絕對值是否在一定的範圍内來進行比較。如,if ( Math.abs(x - y) < .0000001 )

例如:

配置FindBugs和常見FindBugs錯誤

7.11、   Useless assignment in return statement

id: DLS_DEAD_LOCAL_STORE_IN_RETURN, type: DLS, category: STYLE

This statement assigns to a local variable in a return statement. This assignment has effect. Please verify that this statement does the right thing.

原因分析:

在return的對象中,沒有必要通過對象指派再進行傳回。

例如:

配置FindBugs和常見FindBugs錯誤

7.12、   Write to static field from instance method

id: ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD, type: ST, category:STYLE

This instance method writes to a static field. This is tricky to get correct if multiple instances are being manipulated, and generally bad practice.

原因分析:向static字段中寫入值。

例如: 

 private static DBRBO dbrBO; 

 public final void refresh() { 

        danskeBankBO = null; 

        dbrBO = null; 

        fileAndPathBO = null; 

    } 

建議改為:去掉static。

7.13、   Incorrect lazy initialization and update of static field

id: LI_LAZY_INIT_UPDATE_STATIC, type: LI, category: MT_CORRECTNESS

This method contains an unsynchronized lazy initialization of a static field. After the field is set, the object stored into that location is further updated or accessed. The setting of the field is visible to other threads as soon as it is set. If the futher accesses in the method that set the field serve to initialize the object, then you have a very seriousmultithreading bug, unless something else prevents any other thread from accessing the stored object until it is fully initialized.

Even if you feel confident that the method is never called by multiple threads, it might be better to not set the static field until the value you are setting it to is fully populated/initialized.

原因分析:

該方法的初始化中包含了一個遲緩初始化的靜态變量。你的方法引用了一個靜态變量,估計是類靜态變量,那麼多線程調用這個方法時,你的變量就會面臨線程安全的問題了,除非别的東西阻止任何其他線程通路存儲對象從直到它完全被初始化。

7.14、   Method ignores return value

id: RV_RETURN_VALUE_IGNORED, type: RV, category: CORRECTNESS

The return value of this method should be checked. One common cause of this warning is to invoke a method on an immutable object, thinking that it updates the object. For example, in the following code fragment,

String dateString = getHeaderField(name);

dateString.trim();

the programmer seems to be thinking that the trim() method will update the String referenced by dateString. But since Strings are immutable, the trim() function returns a new String value, which is being ignored here. The code should be corrected to:

String dateString = getHeaderField(name);

dateString = dateString.trim();

原因分析:方法忽略了設定傳回值。

例如:

配置FindBugs和常見FindBugs錯誤

7.15、   Method might ignore exception

id: DE_MIGHT_IGNORE, type: DE, category: BAD_PRACTICE

This method might ignore an exception.  In general, exceptions should be handled or reported in some way, or they should be thrown out of the method.

原因分析:應該将異常 處理、列印或者抛出

例如:

配置FindBugs和常見FindBugs錯誤

7.16、   Unwritten field

id: UWF_UNWRITTEN_FIELD, type: UwF, category: CORRECTNESS

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.

原因分析:從未被初始化的變量,調用它時,将傳回預設值,要麼初始化,要麼删掉它。

例如:

配置FindBugs和常見FindBugs錯誤

7.17、   Value is null and guaranteed to be dereferenced on exception path

id: NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH, type: NP, category:CORRECTNESS

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).

原因分析:exception分支上,存在引用一個null對象的方法,引發空指針異常。

例如:

配置FindBugs和常見FindBugs錯誤

7.18、   Very confusing method names

id: NM_VERY_CONFUSING, type: Nm, category: CORRECTNESS

The referenced methods have names that differ only by capitalization. This is very confusing because if the capitalization were identical then one of the methods would override the other.

原因分析:被引用的方法中存在容易混淆的變量。

例如:fzgsdm改成 fzgsDm 即可。

配置FindBugs和常見FindBugs錯誤

7.19、   Method invokes inefficient new String() constructor

id: DM_STRING_VOID_CTOR, type: Dm, category: Performance Creating a new java.lang.String object using the no-argument constructor wastes memory because the object so created will be functionally indistinguishable from the empty string constant "".  Java guarantees that identical string constants will be represented by the same String object.  Therefore, you should just use the empty string constant directly.

原因分析:不使用new String()定義空的字元串

例如:

配置FindBugs和常見FindBugs錯誤

7.20、   Load of known null value

id: NP_LOAD_OF_KNOWN_NULL_VALUE, type: Np, category: Dodgy

The variable referenced at this point is known to be null due to an earlier check against null. Although this is valid, it might be a mistake (perhaps you intended to refer to a different variable, or perhaps the earlier check to see if the variable is null should have been a check to see if it was nonnull).

原因分析:null值的不當使用。

例如:

配置FindBugs和常見FindBugs錯誤

7.21、   Method concatenates strings using + in a loop  

id: SBSC_USE_STRINGBUFFER_CONCATENATION, type: SBSC, category: Performance

The method seems to be building a String using concatenation in a loop. In each iteration, the String is converted to a StringBuffer/StringBuilder, appended to, and converted back to a String. This can lead to a cost quadratic in the number of iterations, as the growing string is recopied in each iteration. Better performance can be obtained by using a StringBuffer (or StringBuilder in Java 1.5) explicitly.

For example:

  // This is bad

  String s = "";

  for (int i = 0; i < field.length; ++i) {

    s = s + field[i];

  }

  // This is better

  StringBuffer buf = new StringBuffer();

  for (int i = 0; i < field.length; ++i) {

    buf.append(field[i]);

  }

  String s = buf.toString();

原因分析:在循環裡使用字元串連接配接,效率低,應該使用StringBuilder/StringBuffer

原文位址:http://www.tuicool.com/articles/YBnIJf

繼續閱讀