天天看點

【Findbugs】Findbugs使用指南

一、簡介

Findbugs是一個靜态分析工具,它檢查類或者jar檔案,将位元組碼與一組缺陷模式進行對比以發現可能的問題。利用這個工具可以在不實際運作程式的情況下對軟體進行分析。可以幫助改進代碼品質。Findbugs提供了友善操作的可視化界面,同時也可以作為eclipse的一個插件來使用,而我們是用的最多的還是作為eclipse插件來使用。

二、使用方法

1、Findbugs的常用操作:

Findbugs找出的bug有三種顔色

黑色的臭蟲标志是分類;

紅色的臭蟲标志表示嚴重bug,發現後必須修改代碼;

橘黃色的臭蟲标志表示潛在警告性bug,應盡量修改;

2、Findbugs的使用方法

Findbugs可以通過三種方法是用:Ant,swing操作界面,eclipse。

2.1 Ant

Ant是一個很好的Java自動執行工具。Findbugs官方提供了Ant的findbugs操作方法,我們可以通過這樣一個build.xml檔案來使用findbugs。

<project name="項目名" default="all">
<property name="findbugs.home" value="findbugs解壓路徑" />
              <path id="findbugs.path">
                  <fileset dir="findbugs解壓路徑">
                        <include name="**/*.jar" />
                   </fileset>
              </path>
              <taskdef name="findbugs"
                   classname="edu.umd.cs.findbugs.anttask.FindBugsTask"
                   classpathref="findbugs.path" />
              <!--  定義findbugs的home,findbugs的task要使用  -->
              <target name="findbugs">
                   <findbugs home="${findbugs.home}"
                        output="xml:withMessages" outputFile="生成的檔案">

                        <!--  以上定義findbugs查找的類路徑  -->
                        <auxClasspath path="${findbugs.home}/lib/findbugs-ant.jar" />
                        <auxClasspath>
                            <fileset dir="lib"
                            includes="*.jar" />
                        </auxClasspath>
                        <sourcePath path="源檔案路徑" />
                        <class location="生成類路徑" />
                   </findbugs>
          </target>
     </project>
           

比如:我這裡有一個項目的findbugs的ant操作的build檔案:

<project name="Calendar" default="all">
<property name="findbugs.home" value="../../findbugs-1.3.8" />
              <path id="findbugs.path">
                  <fileset dir="../../findbugs-1.3.8">
                        <include name="**/*.jar" />
                   </fileset>
              </path>
              <taskdef name="findbugs"
                   classname="edu.umd.cs.findbugs.anttask.FindBugsTask"
                   classpathref="findbugs.path" />
              <!--  定義findbugs的home,findbugs的task要使用  -->
              <target name="findbugs">
                   <mkdir dir="target/findbugs"/>
                   <findbugs home="${findbugs.home}"
                        output="xml:withMessages" outputFile="target/findbugs/calendar-fb.xml">
                        <!--  以上定義findbugs查找的類路徑  -->
                        <auxClasspath path="${findbugs.home}/lib/findbugs-ant.jar" />
                        <auxClasspath>
                            <fileset dir="lib"
                            includes="*.jar" />
                        </auxClasspath>
                        <sourcePath path="src" />
                        <class location="target/classes" />
                   </findbugs>
          </target>
     </project>
           

設定好Ant的環境後,在指令中使用ant -f build.xml,或者在Eclipse直接運作build.xml檔案,運作後生成了一個xml檔案,如果你想用Html的格式檢視findbugs的結果,可以把output屬性設為:html。這樣就可以通過Html來檢視findbugs的結果了。

2.2 swing工具

Ant操作是專家級的操作,一般對于Java不是很熟悉的人,寫build.xml檔案。比起Ant來,使用Findbugs提供的Swing工具會使Findbugs的操作更加簡單。運作Findbugs解壓包中的bin檔案夾下的findbugs.bat檔案,即可開始進行後續的分析工作。

2.3 eclipse

使用eclipse的findbugs插件将findbugs內建到eclipse中,這也是我們平時工作中最常用的一種方法。

下載下傳findbugs插件,解壓之後copy到eclipse的plugin目錄中去,然後重新開機eclipse。打開eclipse->window->Preferences,搜尋關鍵字findbugs,如果能找到配置項,那麼表示安裝成功,如圖:

【Findbugs】Findbugs使用指南

簡單使用:

(1) 在eclipse package Explorer 右鍵選擇目标工程-> build project

【Findbugs】Findbugs使用指南

(2) 選擇指定的包或者類進行findbug

【Findbugs】Findbugs使用指南

此時 周遊指定的包或者類進行分析,找出代碼bug,然後集中顯示在findbugs的bugs explorer中。下面,我們添加bugs explorer。

(3) 添加findbugs explorer (eclipse 左下角)

【Findbugs】Findbugs使用指南
【Findbugs】Findbugs使用指南
【Findbugs】Findbugs使用指南

(4) bugs explorer 添加完畢後,我們就可以檢視剛剛找到的bugs了,如圖:

【Findbugs】Findbugs使用指南

輕按兩下bug項目就可以在右邊編輯視窗自動打開相關代碼檔案并連接配接到代碼片段。 點選行号旁邊的小臭蟲圖示後再eclipse下方輸出區将提供詳細的bug描述,以及修改建議等資訊。我們可以根據此資訊進行修改。

tips1:每次使用Findbugs,檔案夾上右鍵→Findbugs→Findbugs,指令時,如果改動了代碼,需要先BuildProject;

tips2:修改完bug之後,在檔案上右鍵→Findbugs→Clear Bug Marker清除Findbugs的标志。

3、配置Findbugs

你可以對Findbugs的規則進行詳細設定:

3.1 Run Automatically開關

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

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

3.2 Detector Configuration選擇項

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

3.3 Minimum priority to report選擇項

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

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

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

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

3.4 Report bug categories選擇項

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

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

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

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

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

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

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

三、Findbugs的規則

  Findbugs是基于bug patterns概念,查找位元組碼檔案中潛在的bug,主要檢查位元組碼檔案中的bug patterns,如nullpoint空指針檢查、沒有合理關閉資源、字元串相同判斷錯(==而不是equals)等。

1、、Security 關于代碼安全性防護

(1).Dm: Hardcoded constant database password (DMI_CONSTANT_DB_PASSWORD)

代碼中建立DB的密碼時采用了寫死的密碼。

(2).Dm: Empty database password (DMI_EMPTY_DB_PASSWORD)

建立資料庫連接配接時沒有為資料庫設定密碼,這會使資料庫沒有必要的保護。

(3).HRS: HTTP cookie formed from untrusted input (HRS_REQUEST_PARAMETER_TO_COOKIE)

此代碼使用不受信任的HTTP參數構造一個HTTP Cookie。

(4).HRS: HTTP Response splitting vulnerability (HRS_REQUEST_PARAMETER_TO_HTTP_HEADER)

在代碼中直接把一個HTTP的參數寫入一個HTTP頭檔案中,它為HTTP的響應暴露了漏洞。

(5).SQL: Nonconstant string passed to execute method on an SQL statement (SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE)

該方法以字元串的形式來調用SQLstatement的execute方法,它似乎是動态生成SQL語句的方法。這會更容易受到SQL注入攻擊。

(6).XSS: JSP reflected cross site scripting vulnerability (XSS_REQUEST_PARAMETER_TO_JSP_WRITER)

在代碼中在JSP輸出中直接寫入一個HTTP參數,這會造成一個跨站點的腳本漏洞。

2、Experimental試驗性問題

(1).LG: Potential lost logger changes due to weak reference in OpenJDK (LG_LOST_LOGGER_DUE_TO_WEAK_REFERENCE)

OpenJDK的引入了一種潛在的不相容問題,特别是,java.util.logging.Logger的行為改變時。它現在使用内部弱引用,而不是強引用。–logger配置改變,它就是丢失對logger的引用,這本是一個合理的變化,但不幸的是一些代碼對舊的行為有依賴關系。這意味着,當進行垃圾收集時對logger配置将會丢失。例如:

public static void initLogging() throws Exception {

Logger logger = Logger.getLogger(“edu.umd.cs”);

logger.addHandler(new FileHandler()); // call to change logger configuration

logger.setUseParentHandlers(false); // another call to change logger configuration

}

該方法結束時logger的引用就丢失了,如果你剛剛結束調用initLogging方法後進行垃圾回收,logger的配置将會丢失(因為隻有保持記錄器弱引用)。

public static void main(String[] args) throws Exception {

initLogging(); // adds a file handler to the logger

System.gc(); // logger configuration lost

Logger.getLogger(“edu.umd.cs”).info(“Some message”); // this isn’t logged to the file as expected

}

(2).OBL: Method may fail to clean up stream or resource (OBL_UNSATISFIED_OBLIGATION)

這種方法可能無法清除(關閉,處置)一個流,資料庫對象,或其他資源需要一個明确的清理行動。

一般來說,如果一個方法打開一個流或其他資源,該方法應該使用try / finally塊來確定在方法傳回之前流或資源已經被清除了。這種錯誤模式基本上和OS_OPEN_STREAM和ODR_OPEN_DATABASE_RESOURCE錯誤模式相同,但是是在不同在靜态分析技術。我們正為這個錯誤模式的效用收集回報意見。

3、Bad practice代碼實作中的一些壞習慣

(1).AM: Creates an empty jar file entry (AM_CREATES_EMPTY_JAR_FILE_ENTRY)

調用putNextEntry()方法寫入新的 jar 檔案條目時立即調用closeEntry()方法。這樣會造成JarFile條目為空。

(2).AM: Creates an empty zip file entry (AM_CREATES_EMPTY_ZIP_FILE_ENTRY)

調用putNextEntry()方法寫入新的 zip 檔案條目時立即調用closeEntry()方法。這樣會造成ZipFile條目為空。

(3).BC: Equals method should not assume anything about the type of its argument (BC_EQUALS_METHOD_SHOULD_WORK_FOR_ALL_OBJECTS)

equals(Object o)方法不能對參數o的類型做任何的假設。比較此對象與指定的對象。當且僅當該參數不為 null,并且是表示與此對象相同的類型的對象時,結果才為 true。

(4).BC: Random object created and used only once (DMI_RANDOM_USED_ONLY_ONCE)

随機建立對象隻使用過一次就抛棄

(5).BIT: Check for sign of bitwise operation (BIT_SIGNED_CHECK)

檢查位操作符運作是否合理

((event.detail & SWT.SELECTED) > 0)

If SWT.SELECTED is a negative number, this is a candidate for a bug. Even when SWT.SELECTED is not negative, it seems good practice to use ‘!= 0’ instead of ‘> 0’.

(6).CN: Class implements Cloneable but does not define or use clone method (CN_IDIOM)

按照慣例,實作此接口的類應該使用公共方法重寫 Object.clone(它是受保護的),以獲得有關重寫此方法的詳細資訊。此接口不 包含 clone 方法。是以,因為某個對象實作了此接口就克隆它是不可能的,應該實作此接口的類應該使用公共方法重寫 Object.clone

(7).CN: clone method does not call super.clone() (CN_IDIOM_NO_SUPER_CALL)

一個非final類型的類定義了clone()方法而沒有調用super.clone()方法。例如:B擴充自A,如果B中clone方法調用了spuer.clone(),而A中的clone沒有調用spuer.clone(),就會造成結果類型不準确。要求A的clone方法中調用spuer.clone()方法。

(8).CN: Class defines clone() but doesn’t implement Cloneable (CN_IMPLEMENTS_CLONE_BUT_NOT_CLONEABLE)

類中定義了clone方法但是它沒有實作Cloneable接口

(9).Co: Abstract class defines covariant compareTo() method (CO_ABSTRACT_SELF)

抽象類中定義了多個compareTo()方法,正确的是覆寫Comparable中的compareTo方法,方法的參數為Object類型,如下例:

int compareTo(T o) 比較此對象與指定對象的順序。

(10).Co: Covariant compareTo() method defined (CO_SELF_NO_OBJECT)

類中定義了多個compareTo()方法,正确的是覆寫Comparable中的compareTo方法,方法的參數為Object類型

(11).DE: Method might drop exception (DE_MIGHT_DROP)

方法可能抛出異常

(12).DE: Method might ignore exception (DE_MIGHT_IGNORE)

方法可能忽略異常

(13).DMI: Don’t use removeAll to clear a collection (DMI_USING_REMOVEALL_TO_CLEAR_COLLECTION)

不要用removeAll方法去clear一個集合

(14).DP: Classloaders should only be created inside doPrivileged block (DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED)

類加載器隻能建立在特殊的方法體内

(15).Dm: Method invokes System.exit(…) (DM_EXIT)

在方法中調用System.exit(…)語句,考慮用RuntimeException來代替

(16).Dm: Method invokes dangerous method runFinalizersOnExit (DM_RUN_FINALIZERS_ON_EXIT)

在方法中調用了System.runFinalizersOnExit 或者Runtime.runFinalizersOnExit方法,因為這樣做是很危險的。

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

用==或者!=方法去比較String類型的參數

(18).ES: Comparison of String objects using == or != (ES_COMPARING_STRINGS_WITH_EQ)

用==或者!=去比較String類型的對象

(19).Eq: Abstract class defines covariant equals() method (EQ_ABSTRACT_SELF)

(20).Eq: Equals checks for noncompatible operand (EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS)

equals方法檢查不一緻的操作。兩個類根本就是父子關系而去調用equals方法去判讀對象是否相等。

public boolean equals(Object o) {

if (o instanceof Foo)

return name.equals(((Foo)o).name);

else if (o instanceof String)

return name.equals(o);

else return false;

(21).Eq: Class defines compareTo(…) and uses Object.equals() (EQ_COMPARETO_USE_OBJECT_EQUALS)

類中定義了compareTo方法但是繼承了Object中的compareTo方法

(22).Eq: equals method fails for subtypes (EQ_GETCLASS_AND_CLASS_CONSTANT)

類中的equals方法可能被子類中的方法所破壞,當使用類似于Foo.class == o.getClass()的判斷時考慮用this.getClass() == o.getClass()來替換

(23).Eq: Covariant equals() method defined (EQ_SELF_NO_OBJECT)

類中定義了多個equals方法。正确的做法是覆寫Object中的equals方法,它的參數為Object類型的對象。

(24).FI: Empty finalizer should be deleted (FI_EMPTY)

為空的finalizer方法應該删除。一下關于finalizer的内容省略

(25).GC: Unchecked type in generic call (GC_UNCHECKED_TYPE_IN_GENERIC_CALL)

This call to a generic collection method passes an argument while compile type Object where a specific type from the generic type parameters is expected. Thus, neither the standard Java type system nor static analysis can provide useful information on whether the object being passed as a parameter is of an appropriate type.

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

方法定義了equals方法卻沒有定義hashCode方法

(27).HE: Class defines hashCode() but not equals() (HE_HASHCODE_NO_EQUALS)

類定義了hashCode方法去沒有定義equal方法

(28).HE: Class defines equals() and uses Object.hashCode() (HE_EQUALS_USE_HASHCODE)

一個類覆寫了equals方法,沒有覆寫hashCode方法,使用了Object對象的hashCode方法

(29).HE: Class inherits equals() and uses Object.hashCode() (HE_INHERITS_EQUALS_USE_HASHCODE)

子類繼承了父類的equals方法卻使用了Object的hashCode方法

(30).IC: Superclass uses subclass during initialization (IC_SUPERCLASS_USES_SUBCLASS_DURING_INITIALIZATION)

子類在父類未初始化之前使用父類對象執行個體

public class CircularClassInitialization {

static class InnerClassSingleton extends CircularClassInitialization {

static InnerClassSingleton singleton = new InnerClassSingleton();

}

static CircularClassInitialization foo = InnerClassSingleton.singleton;

}

(31).IMSE: Dubious catching of IllegalMonitorStateException (IMSE_DONT_CATCH_IMSE)

捕捉違法的監控狀态異常,例如當沒有擷取到對象鎖時使用其wait和notify方法

(32).ISC: Needless instantiation of class that only supplies static methods (ISC_INSTANTIATE_STATIC_CLASS)

為使用靜态方法而建立一個執行個體對象。調用靜态方法時隻需要使用類名+靜态方法名就可以了。

(33).It: Iterator next() method can’t throw NoSuchElementException (IT_NO_SUCH_ELEMENT)

疊代器的next方法不能夠抛出NoSuchElementException

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

在HttpSession對象中儲存非連續的對象

(35).JCIP: Fields of immutable classes should be final (JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS)

The class is annotated with net.jcip.annotations.Immutable, and the rules for that annotation require that all fields are final. .

(36).NP: Method with Boolean return type returns explicit null (NP_BOOLEAN_RETURN_NULL)

傳回值為boolean類型的方法直接傳回null,這樣會導緻空指針異常

(37).NP: equals() method does not check for null argument (NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT)

變量調用equals方法時沒有進行是否為null的判斷

(38).NP: toString method may return null (NP_TOSTRING_COULD_RETURN_NULL)

toString方法可能傳回null

(39).Nm: Class names should start with an upper case letter (NM_CLASS_NAMING_CONVENTION)

類的名稱以大寫字母名稱開頭

(40).Nm: Class is not derived from an Exception, even though it is named as such (NM_CLASS_NOT_EXCEPTION)

類的名稱中含有Exception但是卻不是一個異常類的子類,這種名稱會造成混淆

(41).Nm: Confusing method names (NM_CONFUSING)

令人迷惑的方面命名

(42).Nm: Field names should start with a lower case letter (NM_FIELD_NAMING_CONVENTION)

非final類型的字段需要遵循駝峰命名原則

(43).Nm: Use of identifier that is a keyword in later versions of Java (NM_FUTURE_KEYWORD_USED_AS_IDENTIFIER)

驗證是否是java預留關鍵字

(44).Nm: Use of identifier that is a keyword in later versions of Java (NM_FUTURE_KEYWORD_USED_AS_MEMBER_IDENTIFIER)

驗證是否時java中的關鍵字

(45).Nm: Method names should start with a lower case letter (NM_METHOD_NAMING_CONVENTION)

方法名稱以小寫字母開頭

(46).Nm: Class names shouldn’t shadow simple name of implemented interface (NM_SAME_SIMPLE_NAME_AS_INTERFACE)

實作同一接口實作類不能使用相同的名稱,即使它們位于不同的包中

(47).Nm: Class names shouldn’t shadow simple name of superclass (NM_SAME_SIMPLE_NAME_AS_SUPERCLASS)

繼承同一父類的子類不能使用相同的名稱,即使它們位于不同的包中

(48).Nm: Very confusing method names (but perhaps intentional) (NM_VERY_CONFUSING_INTENTIONAL)

很容易混淆的方法命名,例如方法的名稱名稱使用使用大小寫來差別兩個不同的方法。

(49).Nm: Method doesn’t override method in superclass due to wrong package for parameter (NM_WRONG_PACKAGE_INTENTIONAL)

由于錯誤引用了不同包中相同類名的對象而不能夠正确的覆寫父類中的方法

import alpha.Foo;

public class A {

public int f(Foo x) { return 17; }

}

import beta.Foo;

public class B extends A {

public int f(Foo x) { return 42; }

public int f(alpha.Foo x) { return 27; }

}

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

方法中可能存在關閉資料連接配接失敗的情況

(51).OS: Method may fail to close stream (OS_OPEN_STREAM)

方法中可能存在關閉流失敗的情況

(52).OS: Method may fail to close stream on exception (OS_OPEN_STREAM_EXCEPTION_PATH)

方法中可能存在關閉流時出現異常情況

(53).RC: Suspicious reference comparison to constant (RC_REF_COMPARISON_BAD_PRACTICE)

當兩者為不同類型的對象時使用equals方法來比較它們的值是否相等,而不是使用==方法。例如比較的兩者為java.lang.Integer, java.lang.Float

(54).RC: Suspicious reference comparison of Boolean values (RC_REF_COMPARISON_BAD_PRACTICE_BOOLEAN)

使用== 或者 !=操作符來比較兩個 Boolean類型的對象,建議使用equals方法。

(55).RR: Method ignores results of InputStream.read() (RR_NOT_CHECKED)

InputStream.read方法忽略傳回的多個字元,如果對結果沒有檢查就沒法正确處理使用者讀取少量字元請求的情況。

(56).RR: Method ignores results of InputStream.skip() (SR_NOT_CHECKED)

InputStream.skip()方法忽略傳回的多個字元,如果對結果沒有檢查就沒法正确處理使用者跳過少量字元請求的情況

(57).RV: Method ignores exceptional return value (RV_RETURN_VALUE_IGNORED_BAD_PRACTICE)

方法忽略傳回值的異常資訊

(58).SI: Static initializer creates instance before all static final fields assigned (SI_INSTANCE_BEFORE_FINALS_ASSIGNED)

在所有的static final字段指派之前去使用靜态初始化的方法建立一個類的執行個體。

(59).Se: Non-serializable value stored into instance field of a serializable class (SE_BAD_FIELD_STORE)

非序列化的值儲存在聲明為序列化的的非序列化字段中

(60).Se: Comparator doesn’t implement Serializable (SE_COMPARATOR_SHOULD_BE_SERIALIZABLE)

Comparator接口沒有實作Serializable接口

(61).Se: Serializable inner class (SE_INNER_CLASS)

序列化内部類

(62).Se: serialVersionUID isn’t final (SE_NONFINAL_SERIALVERSIONID)

關于UID類的檢查内容省略

(63).Se: Class is Serializable but its superclass doesn’t define a void constructor (SE_NO_SUITABLE_CONSTRUCTOR)

子類序列化時父類沒有提供一個void的構造函數

(64).Se: Class is Externalizable but doesn’t define a void constructor (SE_NO_SUITABLE_CONSTRUCTOR_FOR_EXTERNALIZATION)

Externalizable 執行個體類沒有定義一個void類型的構造函數

(65).Se: The readResolve method must be declared with a return type of Object. (SE_READ_RESOLVE_MUST_RETURN_OBJECT)

readResolve從流中讀取類的一個執行個體,此方法必須聲明傳回一個Object類型的對象

(66).Se: Transient field that isn’t set by deserialization. (SE_TRANSIENT_FIELD_NOT_RESTORED)

This class contains a field that is updated at multiple places in the class, thus it seems to be part of the state of the class. However, since the field is marked as transient and not set in readObject or readResolve, it will contain the default value in any deserialized instance of the class.

(67).SnVI: Class is Serializable, but doesn’t define serialVersionUID (SE_NO_SERIALVERSIONID)

一個類實作了Serializable接口但是沒有定義serialVersionUID類型的變量。序列化運作時使用一個稱為 serialVersionUID 的版本号與每個可序列化類相關聯,該序列号在反序列化過程中用于驗證序列化對象的發送者和接收者是否為該對象加載了與序列化相容的類。如果接收者加載的該對象的類的 serialVersionUID 與對應的發送者的類的版本号不同,則反序列化将會導緻 InvalidClassException。可序列化類可以通過聲明名為 “serialVersionUID” 的字段(該字段必須是靜态 (static)、最終 (final) 的 long 型字段)顯式聲明其自己的 serialVersionUID:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

(68).UI: Usage of GetResource may be unsafe if class is extended (UI_INHERITANCE_UNSAFE_GETRESOURCE)

當一個類被子類繼承後不要使用this.getClass().getResource(…)來擷取資源

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

(1).BC: Impossible cast (BC_IMPOSSIBLE_CAST)

不可能的類轉換,執行時會抛出ClassCastException

(2).BC: Impossible downcast (BC_IMPOSSIBLE_DOWNCAST)

父類在向下進行類型轉換時抛出ClassCastException

(3).BC: Impossible downcast of toArray() result (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).

(4).BC: instanceof will always return false (BC_IMPOSSIBLE_INSTANCEOF)

采用instaneof方法進行比較時總是傳回false。前提是保證它不是由于某些邏輯錯誤造成的。

(5).BIT: Incompatible bit masks (BIT_AND)

錯誤的使用&位操作符,例如(e & C)

(6).BIT: Check to see if ((…) & 0) == 0 (BIT_AND_ZZ)

檢查恒等的邏輯錯誤

(7).BIT: Incompatible bit masks (BIT_IOR)

錯誤的使用|位操作符,例如(e | C)

(8).BIT: Check for sign of bitwise operation (BIT_SIGNED_CHECK_HIGH_BIT)

檢查邏輯運算符操作傳回的辨別。例如((event.detail & SWT.SELECTED) > 0),建議采用!=0代替>0

(9).BOA: Class overrides a method implemented in super class Adapter wrongly (BOA_BADLY_OVERRIDDEN_ADAPTER)

子類錯誤的覆寫父類中用于适配監聽其他事件的方法,進而導緻當觸發條件發生時不能被監聽者調用

(10).Bx: Primitive value is unboxed and coerced for ternary operator (BX_UNBOXED_AND_COERCED_FOR_TERNARY_OPERATOR)

在三元運算符操作時如果沒有對值進行封裝或者類型轉換。例如:b ? e1 : e2

(11).DLS: Dead store of class literal (DLS_DEAD_STORE_OF_CLASS_LITERAL)

以類的字面名稱方式為一個字段指派後再也沒有去使用它,在1.4jdk中它會自動調用靜态的初始化方法,而在jdk1.5中卻不會去執行。

(12).DLS: Overwritten increment (DLS_OVERWRITTEN_INCREMENT)

覆寫增量增加錯誤i = i++

(13).DMI: Bad constant value for month (DMI_BAD_MONTH)

hashNext方法調用next方法。

(14).DMI: Collections should not contain themselves (DMI_COLLECTIONS_SHOULD_NOT_CONTAIN_THEMSELVES)

集合沒有包含他們自己本身。

(15).DMI: Invocation of hashCode on an array (DMI_INVOKING_HASHCODE_ON_ARRAY)

數組直接使用hashCode方法來傳回哈希碼。

int [] a1 = new int[]{1,2,3,4};

System.out.println(a1.hashCode());

System.out.println(java.util.Arrays.hashCode(a1));

(16).DMI: Double.longBitsToDouble invoked on an int (DMI_LONG_BITS_TO_DOUBLE_INVOKED_ON_INT)

(17).DMI: Vacuous call to collections (DMI_VACUOUS_SELF_COLLECTION_CALL)

集合的調用不能被感覺。例如c.containsAll(c)總是傳回true,而c.retainAll(c)的傳回值不能被感覺。

(18).Dm: Can’t use reflection to check for presence of annotation without runtime retention (DMI_ANNOTATION_IS_NOT_VISIBLE_TO_REFLECTION)

Unless an annotation has itself been annotated with @Retention(RetentionPolicy.RUNTIME), the annotation can’t be observed using reflection (e.g., by using the isAnnotationPresent method). .

(19).Dm: Useless/vacuous call to EasyMock method (DMI_VACUOUS_CALL_TO_EASYMOCK_METHOD)

While ScheduledThreadPoolExecutor inherits from ThreadPoolExecutor, a few of the inherited tuning methods are not useful for it. In particular, because it acts as a fixed-sized pool using corePoolSize threads and an unbounded queue, adjustments to maximumPoolSize have no useful effect.

(20).EC: equals() used to compare array and nonarray (EC_ARRAY_AND_NONARRAY)

數組對象使用equals方法和非數組對象進行比較。即使比較的雙方都是數組對象也不應該使用equals方法,而應該比較它們的内容是否相等使用java.util.Arrays.equals(Object[], Object[]);

(21).EC: equals(…) used to compare incompatible arrays (EC_INCOMPATIBLE_ARRAY_COMPARE)

使用equls方法去比較類型不相同的數組。例如:String[] and StringBuffer[], or String[] and int[]

(22).EC: Call to equals() with null argument (EC_NULL_ARG)

調用equals的對象為null

(23).EC: Call to equals() comparing unrelated class and interface (EC_UNRELATED_CLASS_AND_INTERFACE)

使用equals方法比較不相關的類和接口

(24).EC: Call to equals() comparing different interface types (EC_UNRELATED_INTERFACES)

調用equals方法比較不同類型的接口

(25).EC: Call to equals() comparing different types (EC_UNRELATED_TYPES)

調用equals方法比較不同類型的類

(26).EC: Using pointer equality to compare different types (EC_UNRELATED_TYPES_USING_POINTER_EQUALITY)

This method uses using pointer equality to compare two references that seem to be of different types. The result of this comparison will always be false at runtime.

(27).Eq: equals method always returns false (EQ_ALWAYS_FALSE)

使用equals方法傳回值總是false

(28).Eq: equals method always returns true (EQ_ALWAYS_TRUE)

equals方法傳回值總是true

(29).Eq: equals method compares class names rather than class objects (EQ_COMPARING_CLASS_NAMES)

使用equals方法去比較一個類的執行個體和類的類型

(30).Eq: Covariant equals() method defined for enum (EQ_DONT_DEFINE_EQUALS_FOR_ENUM)

This class defines an enumeration, and equality on enumerations are defined using object identity. Defining a covariant equals method for an enumeration value is exceptionally bad practice, since it would likely result in having two different enumeration values that compare as equals using the covariant enum method, and as not equal when compared normally. Don’t do it.

(31).Eq: equals() method defined that doesn’t override equals(Object) (EQ_OTHER_NO_OBJECT)

類中定義的equals方法時不要覆寫equals(Object)方法

(32).Eq: equals() method defined that doesn’t override Object.equals(Object) (EQ_OTHER_USE_OBJECT)

類中定義的equals方法時不要覆寫Object中的equals(Object)方法

(33).Eq: equals method overrides equals in superclass and may not be symmetric (EQ_OVERRIDING_EQUALS_NOT_SYMMETRIC)

(34).Eq: Covariant equals() method defined, Object.equals(Object) inherited (EQ_SELF_USE_OBJECT)

類中定義了一組equals方法,但是都是繼承的java.lang.Object class中的equals(Object)方法

(35).FE: Doomed test for equality to NaN (FE_TEST_IF_EQUAL_TO_NOT_A_NUMBER)

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

(36).FS: Format string placeholder incompatible with passed argument (VA_FORMAT_STRING_BAD_ARGUMENT)

錯誤使用參數類型來格式化字元串

(37).FS: The type of a supplied argument doesn’t match format specifier (VA_FORMAT_STRING_BAD_CONVERSION)

指定的格式字元串和參數類型不比對,例如:String.format(“%d”, “1”)

(38).FS: MessageFormat supplied where printf style format expected (VA_FORMAT_STRING_EXPECTED_MESSAGE_FORMAT_SUPPLIED)

但用String的format方法時實際調用了MessageFormat中幹的格式化方法而引起格式化結果出錯。

(39).FS: More arguments are passed than are actually used in the format string (VA_FORMAT_STRING_EXTRA_ARGUMENTS_PASSED)

使用String的format方法時有非法的參數也經過了格式化操作。

(40).FS: Illegal format string (VA_FORMAT_STRING_ILLEGAL)

格式化String對象語句錯誤

(41).FS: Format string references missing argument (VA_FORMAT_STRING_MISSING_ARGUMENT)

String的format操作缺少必要的參數。

(42).FS: No previous argument for format string (VA_FORMAT_STRING_NO_PREVIOUS_ARGUMENT)

格式字元串定義錯誤,

例如:

formatter.format("%<s %s", "a", "b");

抛出MissingFormatArgumentException異常

(43).GC: No relationship between generic parameter and method argument (GC_UNRELATED_TYPES)

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 contains a Foo, the equals method of argument (e.g., the equals method of the Foo class) used to perform the equality checks.

(44).HE: Signature declares use of unhashable class in hashed construct (HE_SIGNATURE_DECLARES_HASHING_OF_UNHASHABLE_CLASS)

A method, field or class declares a generic signature where a non-hashable class is used in context where a hashable class is required. A class that declares an equals method but inherits a hashCode() method from Object is unhashable, since it doesn’t fulfill the requirement that equal objects have equal hashCodes.

(45).HE: Use of class without a hashCode() method in a hashed data structure (HE_USE_OF_UNHASHABLE_CLASS)

A class defines an equals(Object) method but not a hashCode() method, and thus doesn’t fulfill the requirement that equal objects have equal hashCodes. An instance of this class is used in a hash data structure, making the need to fix this problem of highest importance.

(46).ICAST: integral value cast to double and then passed to Math.ceil (ICAST_INT_CAST_TO_DOUBLE_PASSED_TO_CEIL)

integral的值轉換為double後使用了Math.ceil方法

(47).ICAST: int value cast to float and then passed to Math.round (ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND)

int 類型的值轉換為float類型之後調用了Math.round方法

(48).IJU: JUnit assertion in run method will not be noticed by JUnit (IJU_ASSERT_METHOD_INVOKED_FROM_RUN_METHOD)

在JUnit中的斷言在run方法中不會被告知

(49).IJU: TestCase declares a bad suite method (IJU_BAD_SUITE_METHOD)

在一個JUnit類中聲明的一個suite()方法必須聲明為

public static junit.framework.Test suite()

或者

public static junit.framework.TestSuite suite()的形式。

(50).IL: A collection is added to itself (IL_CONTAINER_ADDED_TO_ITSELF)

集合本身作為add方法的參數,這樣會引起内容溢出。

(51).IL: An apparent infinite loop (IL_INFINITE_LOOP)

方法的自調用引起的死循環

(52).IM: Integer multiply of result of integer remainder (IM_MULTIPLYING_RESULT_OF_IREM)

和整數餘數進行乘法運算。例如:i % 60 * 1000 是進行(i % 60) * 1000運算而不是 i % (60 * 1000)

(53).INT: Bad comparison of nonnegative value with negative constant (INT_BAD_COMPARISON_WITH_NONNEGATIVE_VALUE)

保證非負數和負數進行比較

(54).INT: Bad comparison of signed byte (INT_BAD_COMPARISON_WITH_SIGNED_BYTE)

比較有符合數,要先把有符号數轉換為無符合數再進行比較

(55).IO: Doomed attempt to append to an object output stream (IO_APPENDING_TO_OBJECT_OUTPUT_STREAM)

宣布試圖在對象的輸出流處添加元素,如果你希望能夠添加進一個對象的輸出流中必須保證對象的輸出流處于打開狀态。

(56).IP: A parameter is dead upon entry to a method but overwritten (IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN)

The initial value of this parameter is ignored, and the parameter is overwritten here. This often indicates a mistaken belief that the write to the parameter will be conveyed back to the caller.

傳入參數的值被忽略,但是對傳入值進行了修改,并傳回給了調用者

(57).MF: Class defines field that masks a superclass field (MF_CLASS_MASKS_FIELD)

子類中定義了和父類中同名的字段。在調用時會出錯

(58).MF: Method defines a variable that obscures a field (MF_METHOD_MASKS_FIELD)

在方法中定義的局部變量和類變量或者父類變量同名,進而引起字段混淆。

(59).NP: Null pointer dereference (NP_ALWAYS_NULL)

對象賦為null值後 沒有被重新指派

(60).NP: Null pointer dereference in method on exception path (NP_ALWAYS_NULL_EXCEPTION)

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.

空指針引用上調用去除引用方法,将發生空指針異常

(61).NP: Method does not check for null argument (NP_ARGUMENT_MIGHT_BE_NULL)

方法沒有判斷參數是否為空

(62).NP: close() invoked on a value that is always null (NP_CLOSING_NULL)

一個為空的對象調用close方法

(63).NP: Null value is guaranteed to be dereferenced (NP_GUARANTEED_DEREF)

There is a statement or branch 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判斷分支上,對象去除引用操作是受保護的不允許的

(64).NP: Value is null and guaranteed to be dereferenced on exception path (NP_GUARANTEED_DEREF_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).

(65).NP: Method call passes null to a nonnull parameter (NP_NONNULL_PARAM_VIOLATION)

方法中為null的參數沒有被重新指派

void test(){

String ss = null;

sya(ss);

}

public void sya(String ad){

ad.getBytes();

}

(66).NP: Method may return null, but is declared @NonNull (NP_NONNULL_RETURN_VIOLATION)

方法聲明了傳回值不能為空,但是方法中有可能傳回null

(67).NP: A known null value is checked to see if it is an instance of a type (NP_NULL_INSTANCEOF)

檢查一個為null的值是否是想要的類型對象,而不是由于粗心或者邏輯錯誤引起的

(68).NP: Possible null pointer dereference (NP_NULL_ON_SOME_PATH)

對象可能沒有重新指派

(69).NP: Possible null pointer dereference in method on exception path (NP_NULL_ON_SOME_PATH_EXCEPTION)

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值處理分支調用的方法上,可能存在對象去除引用操作

(70).NP: Method call passes null for nonnull parameter (NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS)

方法參數中聲明為nonnull類型的參數為null

void test(){

String ss = null;

sya(ss);

}

public void sya(@nonnull String ad){

ad.getBytes();

}

(71).NP: Store of null value into field annotated NonNull (NP_STORE_INTO_NONNULL_FIELD)

為一個已經聲明為不能為null值的屬性指派為null。

(72).Nm: Class defines equal(Object); should it be equals(Object)? (NM_BAD_EQUAL)

類中定義了一個equal方法但是卻不是覆寫的Object對象的equals方法

(73).Nm: Class defines hashcode(); should it be hashCode()? (NM_LCASE_HASHCODE)

類中定義了一個hashCode方法但是卻不是覆寫的Object中的hashCode方法

(74).Nm: Class defines tostring(); should it be toString()? (NM_LCASE_TOSTRING)

類中定義了一個toString方法但是卻不是覆寫的Object中的toString方法

(75).Nm: Apparent method/constructor confusion (NM_METHOD_CONSTRUCTOR_CONFUSION)

構造方法定義混亂,保證一個标準的構造函數。例如:

SA(){}

void SA(){

}

(76).Nm: Very confusing method names (NM_VERY_CONFUSING)

混亂的方法命名,如getName和getname方法同時出現的時候

(77).Nm: Method doesn’t override method in superclass due to wrong package for parameter (NM_WRONG_PACKAGE)

方法因為取了不同包中的同名的對象而沒有正确覆寫父類中的同名方法

import alpha.Foo;

public class A {

public int f(Foo x) { return 17; }

}

import beta.Foo;

public class B extends A {

public int f(Foo x) { return 42; }

}

(78).QBA: Method assigns boolean literal in boolean expression (QBA_QUESTIONABLE_BOOLEAN_ASSIGNMENT)

再if或者while表達式中使用boolean類型的值時應該使用==去判斷,而不是采用=操作

(79).RC: Suspicious reference comparison (RC_REF_COMPARISON)

比較兩個對象值是否相等時應該采用equals方法,而不是==方法

(80).RE: Invalid syntax for regular expression (RE_BAD_SYNTAX_FOR_REGULAR_EXPRESSION)

對正規表達式使用了錯誤的文法,會抛出未經檢查的異常,表明正規表達式模式中的文法錯誤。

(81).RE: File.separator used for regular expression (RE_CANT_USE_FILE_SEPARATOR_AS_REGULAR_EXPRESSION)

使用正規表達式使用了錯誤的檔案分隔符,在windows系統中正規表達式不會比對’\’而應該使用’\’

(82).RV: Random value from 0 to 1 is coerced to the integer 0 (RV_01_TO_INT)

從0到1随機值被強制為整數值0。在強制得到一個整數之前,你可能想得到多個随機值。或使用Random.nextInt(n)的方法。

(83).RV: Bad attempt to compute absolute value of signed 32-bit hashcode (RV_ABSOLUTE_VALUE_OF_HASHCODE)

此代碼生成一個哈希碼,然後計算該哈希碼的絕對值。如果哈希碼是Integer.MIN_VALUE的,那麼結果将是負數(因為Math.abs(Integer.MIN_VALUE的)== Integer.MIN_VALUE的)。

在2^ 32值之外字元串有一個Integer.MIN_VALUE的hashCode包括“polygenelubricants”,“GydZG_”和“,”DESIGNING WORKHOUSES “。

(84).RV: Bad attempt to compute absolute value of signed 32-bit random integer (RV_ABSOLUTE_VALUE_OF_RANDOM_INT)

此代碼生成一個随機的符号整數,然後計算該随機整數的絕對值。如果随機數生成數絕對值為Integer.MIN_VALUE的,那麼結果将是負數(因為Math.abs(Integer.MIN_VALUE的)== Integer.MIN_VALUE的)。

(85).RV: Exception created and dropped rather than thrown (RV_EXCEPTION_NOT_THROWN)

此代碼建立一個異常(或錯誤)的對象,但不會用它做任何事情。例如:if (x < 0)

new IllegalArgumentException(“x must be nonnegative”);

這可能是程式員的意圖抛出建立的異常:

if (x < 0)

throw new IllegalArgumentException(“x must be nonnegative”);

(86).RV: Method ignores return value (RV_RETURN_VALUE_IGNORED)

該方法的傳回值應該進行檢查。這種警告通常出現在調用一個不可變對象的方法,認為它更新了對象的值。例如:String dateString = getHeaderField(name);

dateString.trim();

程式員似乎以為trim()方法将更新dateString引用的字元串。但由于字元串是不可改變的,trim()函數傳回一個新字元串值,在這裡它是被忽略了。該代碼應更正:

String dateString = getHeaderField(name);

dateString = dateString.trim();

(87).RpC: Repeated conditional tests (RpC_REPEATED_CONDITIONAL_TEST)

該代碼包含對同一個條件試驗了兩次,兩邊完全一樣例如:(如X == 0 | | x == 0)。可能第二次出現是打算判斷别的不同條件(如X == 0 | | y== 0)。

(88).SA: Double assignment of field (SA_FIELD_DOUBLE_ASSIGNMENT)

方法中的字段包含了雙重任務,例如:

int x;

public void foo() {

x = x = 17;

}

這種為變量指派是無用的,并可能表明一個邏輯錯誤或拼寫錯誤。

(89).SA: Self assignment of field (SA_FIELD_SELF_ASSIGNMENT)

方法中包含自己對自己指派的字段。例如:

int x;

public void foo() {

x = x;

}

(90).SA: Self comparison of field with itself (SA_FIELD_SELF_COMPARISON)

字段自己進行自比較可能表明錯誤或邏輯錯誤。

(91).SA: Self comparison of value with itself (SA_LOCAL_SELF_COMPARISON)

方法中對一個局部變量自身進行比較運算,并可說明錯誤或邏輯錯誤。請確定您是比較正确的事情。

(92).SA: Nonsensical self computation involving a variable (e.g., x & x) (SA_LOCAL_SELF_COMPUTATION)

此方法對同一變量執行了荒謬的計算(如x&x或x-x)操作。由于計算的性質,這一行動似乎沒有意義,并可能表明錯誤或邏輯錯誤。

(93).SF: Dead store due to switch statement fall through (SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH)

在swtich中先前的case值因為swtich執行失敗而被覆寫,這就像是忘記使用break推出或者沒有使用return語句放回先前的值一樣。

(94).SF: Dead store due to switch statement fall through to throw (SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH_TO_THROW)

在swtich中因為出現異常而忽略了對case值的儲存。

(95).SIC: Deadly embrace of non-static inner class and thread local (SIC_THREADLOCAL_DEADLY_EMBRACE)

如果是一個靜态内部類。實際上,在内部類和目前線程有死鎖的可能。由于内部類不是靜态的,它保留了對外部類的引用。如果線程包含對一個内部類執行個體的引用,那麼内外執行個體的執行個體都可以被擷取,這樣就不具備垃圾會回收的資格。

(96).SIO: Unnecessary type check done using instanceof operator (SIO_SUPERFLUOUS_INSTANCEOF)

在進行instanceof操作時進行沒有必要的類型檢查

(97).STI: Unneeded use of currentThread() call, to call interrupted() (STI_INTERRUPTED_ON_CURRENTTHREAD)

此方法調用Thread.currentThread()調用,隻需調用interrupted()方法。由于interrupted()是一個靜态方法, Thread.interrupted()更簡單易用。

(98).STI: Static Thread.interrupted() method invoked on thread instance (STI_INTERRUPTED_ON_UNKNOWNTHREAD)

調用不是目前線程對象的Thread.interrupted()方法,由于interrupted()方法是靜态的,interrupted方法将會調用一個和作者原計劃不同的對象。

(99).Se: Method must be private in order for serialization to work (SE_METHOD_MUST_BE_PRIVATE)

這個類實作了Serializable接口,并定義自定義序列化的方法/反序列化。但由于這種方法不能聲明為private,将被序列化/反序列化的API忽略掉。

(100).Se: The readResolve method must not be declared as a static method. (SE_READ_RESOLVE_IS_STATIC)

為使readResolve方法得到序列化機制的識别,不能作為一個靜态方法來聲明。

(101).UMAC: Uncallable method defined in anonymous class (UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS)

在匿名類中定義了一個既沒有覆寫超類中方法也不能直接調用的方法。因為在其他類的方法不能直接引用匿名類聲明的方法,似乎這種方法不能被調用,這種方法可能隻是沒有任何作用的代碼,但也可能覆寫超類中聲明。

(102).UR: Uninitialized read of field in constructor (UR_UNINIT_READ)

此構造方法中使用了一個尚未指派的字段或屬性。

String a;

public SA() {

String abc = a;

System.out.println(abc);

}

(103).UR: Uninitialized read of field method called from constructor of superclass (UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR)

方法被超類的構造函數調用時,在目前類中的字段或屬性還沒有被初始化。例如:

abstract class A {

int hashCode;

abstract Object getValue();

A() {

hashCode = getValue().hashCode();

}

}

class B extends A {

Object value;

B(Object v) {

this.value = v;

}

Object getValue() {

return value;

}

}

當B是建立時,A的構造函數将在B為value指派之前觸發,然而在A的初始化方法調用getValue方法時value這個變量還沒有被初始化。

(104).USELESS_STRING: Invocation of toString on an array (DMI_INVOKING_TOSTRING_ON_ANONYMOUS_ARRAY)

該代碼調用上匿名數組的toString()方法,産生的結果形如[@ 16f0472并沒有實際的意義。考慮使用Arrays.toString方法來轉換成可讀的字元串,提供該數組的内容數組。例如:

String[] a = { “a” };

System.out.println(a.toString());

//正确的使用為

System.out.println(Arrays.toString(a));

(105).USELESS_STRING: Invocation of toString on an array (DMI_INVOKING_TOSTRING_ON_ARRAY)

該代碼調用上數組的toString()方法,産生的結果形如[@ 16f0472并不能顯示數組的真實内容。考慮使用Arrays.toString方法來轉換成可讀的字元串,提供該數組的内容數組

(106).UwF: Field only ever set to null (UWF_NULL_FIELD)

字段的值總是為null值,所有讀取該字段的值都為null。檢查錯誤,如果它确實沒有用就删除掉。

(107).UwF: Unwritten field (UWF_UNWRITTEN_FIELD

此字段是永遠不會寫入值。所有讀取将傳回預設值。檢查錯誤(如果它被初始化?),如果它确實沒有用就删除掉。

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

(1).Bx: Primitive value is boxed and then immediately unboxed (BX_BOXING_IMMEDIATELY_UNBOXED)

對原始值進行裝箱,然後立即取消裝箱。這可能是在一個未要求裝箱的地方進行了手動裝箱,進而迫使編譯器進行立即撤消裝箱的操作

(2).Bx: Primitive value is boxed then unboxed to perform primitive coercion (BX_BOXING_IMMEDIATELY_UNBOXED_TO_PERFORM_COERCION)

對原始值進行裝箱然後立即把它強制轉換為另外一種原始類型。例如:

new Double(d).intValue()應該直接進行強制轉換例如:(int) d

(3).Bx: Method allocates a boxed primitive just to call toString (DM_BOXED_PRIMITIVE_TOSTRING)

僅僅為了調用封裝類的toString()而對原始類型進行封裝操作。比這種方法更有效的是調用封裝類的toString(…)方法例如:

new Integer(1).toString() 替換為 Integer.toString(1)

new Long(1).toString() 替換為 Long.toString(1)

new Float(1.0).toString() 替換為 Float.toString(1.0)

new Double(1.0).toString() 替換為 Double.toString(1.0)

new Byte(1).toString() 替換為 Byte.toString(1)

new Short(1).toString() 替換為 Short.toString(1)

new Boolean(true).toString() 替換為 Boolean.toString(true)

(4).Bx: Method invokes inefficient floating-point Number constructor; use static valueOf instead (DM_FP_NUMBER_CTOR)

使用new Double(double)方法總是會建立一個新的對象,然而使用Double.valueOf(double)方法可以把值儲存在編輯器或者class library、JVM中。使用存儲值的方式來避免對象的配置設定可以或得更好的代碼性能

除非類必須符合Java 1.5以前的JVM,否則請使用自動裝箱或valueOf()方法建立Double和Float執行個體。

(5).Bx: Method invokes inefficient Number constructor; use static valueOf instead (DM_NUMBER_CTOR)

使用new Integer(int)方法總是會建立一個新的對象,然而使用Integer.valueOf(int)方法可以把值儲存在編輯器或者class library、JVM中。使用存儲值的方式來避免對象的配置設定可以或得更好的代碼性能

除非類必須符合Java 1.5以前的JVM,否則請使用自動裝箱或valueOf()方法建立Long, Integer, Short, Character, Byte執行個體。

(6).Dm: The equals and hashCode methods of URL are blocking (DMI_BLOCKING_METHODS_ON_URL)

使用equals和hashCode方法來對url進行資源辨別符解析時會引起堵塞。考慮使用java.net.URI來代替。

(7).Dm: Maps and sets of URLs can be performance hogs (DMI_COLLECTION_OF_URLS)

方法或者字段使用url的map/set集合。因為equals方法或者hashCode方法來進行資源辨別符解析時都會引起堵塞。考慮使用java.net.URI來代替。

(8).Dm: Method invokes inefficient Boolean constructor; use Boolean.valueOf(…) instead (DM_BOOLEAN_CTOR)

使用new方法建立一個java.lang.Boolean類型能夠的執行個體對象是浪費空間的,因為Boolean對象是不可變的而且隻有兩個有用的值。使用Boolean.valueOf()或者Java1.5中的自動裝箱功能來建立一個Boolean執行個體。

(9).Dm: Explicit garbage collection; extremely dubious except in benchmarking code (DM_GC)

在代碼中顯式的調用垃圾回收命名,這樣做并不能起作用。在過去,有人在關閉操作或者finalize方法中調用垃圾回收方法導緻了很多的性能浪費。這樣大規模回收對象時會造成處理器運作緩慢。

(10).Dm: Use the nextInt method of Random rather than nextDouble to generate a random integer (DM_NEXTINT_VIA_NEXTDOUBLE)

如果r是一個java.util.Random對象,你可以使r.nextInt(n)生成一個0到n-1之前的随機數,而不是使用(int)(r.nextDouble() * n)

(11).Dm: Method invokes inefficient new String(String) constructor (DM_STRING_CTOR)

使用java.lang.String(String)構造函數會浪費記憶體因為這種構造方式和String作為參數在功能上容易混亂。隻是使用String直接作為參數的形式

(12).Dm: Method invokes toString() method on a String (DM_STRING_TOSTRING)

調用String.toString()是多餘的操作,隻要使用String就可以了。

(13).Dm: Method invokes inefficient new String() constructor (DM_STRING_VOID_CTOR)

使用沒有參數的構造方法去建立新的String對象是浪費記憶體空間的,因為這樣建立會和空字元串“”混淆。Java中保證完成相同的構造方法會産生描繪相同的String對象。是以你隻要使用空字元串來建立就可以了。

(14).ITA: Method uses toArray() with zero-length array argument (ITA_INEFFICIENT_TO_ARRAY)

當使用集合的toArray()方法時使用數組長度為0的數組作為參數。比這更有效的一種方法是

myCollection.toArray(new Foo[myCollection.size()]),如果數組的長度足夠大就可以直接把集合中的内容包裝到數組中直接傳回進而避免了第二次建立一個新的數組來存放集合中值。

(15).SBSC: Method concatenates strings using + in a loop (SBSC_USE_STRINGBUFFER_CONCATENATION)

在循環中建構一個String對象時從性能上講使用StringBuffer來代替String對象

例如:

// 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();

(16).SS: Unread field: should this field be static? (SS_SHOULD_BE_STATIC)

類中所包含的final屬性字段在編譯器中初始化為靜态的值。考慮在定義時就把它定義為static類型的。

(17).UM: Method calls static Math class method on a constant value (UM_UNNECESSARY_MATH)

在方法中使用了java.lang.Math的靜态方法代替常量來使用,使用常量速度和準确度會更好。 以下為Math中的方法産生的值。

Method Parameter

abs -any-

acos 0.0 or 1.0

asin 0.0 or 1.0

atan 0.0 or 1.0

atan2 0.0 cbrt 0.0 or 1.0

ceil -any-

cos 0.0

cosh 0.0

exp 0.0 or 1.0

expm1 0.0

floor -any-

log 0.0 or 1.0

log10 0.0 or 1.0

rint -any-

round -any-

sin 0.0

sinh 0.0

sqrt 0.0 or 1.0

tan 0.0

tanh 0.0

toDegrees 0.0 or 1.0

toRadians 0.0

(18).UPM: Private method is never called (UPM_UNCALLED_PRIVATE_METHOD)

定義為Private類型方法從未被調用,應該被删除。

(19).UrF: Unread field (URF_UNREAD_FIELD)

類中定義的屬性從未被調用,建議删除。

(20).UuF: Unused field (UUF_UNUSED_FIELD)

類中定義的屬性從未被使用,建議删除。

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

當方法中接受一個Map類型的參數時,使用keySet的疊代器比使用entrySet的疊代器效率要高。

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

Dm: Consider using Locale parameterized version of invoked method (DM_CONVERT_CASE)

使用平台預設的編碼格式對字元串進行大小寫轉換,這可能導緻國際字元的轉換不當。使用以下方式對字元進行轉換

String.toUpperCase( Locale l )

String.toLowerCase( Locale l )

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

(1).DL: Synchronization on Boolean could lead to deadlock (DL_SYNCHRONIZATION_ON_BOOLEAN)

該代碼同步一個封裝的原始常量,例如一個Boolean類型。

private static Boolean inited = Boolean.FALSE;

synchronized(inited) {

if (!inited) {

init();

inited = Boolean.TRUE;

}

}

由于通常隻存在兩個布爾對象,此代碼可能是同步的其他無關的代碼中相同的對象,這時會導緻反應遲鈍和可能死鎖

(2).DL: Synchronization on boxed primitive could lead to deadlock (DL_SYNCHRONIZATION_ON_BOXED_PRIMITIVE)

該代碼同步一個封裝的原始常量,例如一個Integer類型。

private static Integer count = 0;

synchronized(count) {

count++;

}

由于Integer對象可以共享和儲存,此代碼可能是同步的其他無關的代碼中相同的對象,這時會導緻反應遲鈍和可能死鎖

(3).DL: Synchronization on interned String could lead to deadlock (DL_SYNCHRONIZATION_ON_SHARED_CONSTANT)

同步String類型的常量時,由于它被JVM中多個其他的對象所共有,這樣在其他代碼中會引起死鎖。

(4).DL: Synchronization on boxed primitive values (DL_SYNCHRONIZATION_ON_UNSHARED_BOXED_PRIMITIVE)

同步一個顯然不是共有封裝的原始值,例如一個Integer類型的對象。例如:

private static final Integer fileLock = new Integer(1);

synchronized(fileLock) {

.. do something ..

}

它最後被定義為以下方式來代替:private static final Object fileLock = new Object();

(5).Dm: Monitor wait() called on Condition (DM_MONITOR_WAIT_ON_CONDITION)

方法中以java.util.concurrent.locks.Condition對象調用wait()。等待一個條件發生時應該使用在Condition接口中定義的await()方法。

(6).Dm: A thread was created using the default empty run method (DM_USELESS_THREAD)

這個方法沒有通過run方法或者具體聲明Thread類,也沒有通過一個Runnable對象去定義一個線程,而這個線程出來浪費資源卻什麼也沒有去做。

(7).ESync: Empty synchronized block (ESync_EMPTY_SYNC)

該代碼包含一個空的同步塊:synchronized() {}

(8).IS: Inconsistent synchronization (IS2_INCONSISTENT_SYNC)

不合理的同步

(9).IS: Field not guarded against concurrent access (IS_FIELD_NOT_GUARDED)

域不是良好的同步通路—

此字段被标注為net.jcip.annotations.GuardedBy,但可以在某種程度上違反注釋而去通路

(10).JLM: Synchronization performed on Lock (JLM_JSR166_LOCK_MONITORENTER)

實作java.util.concurrent.locks.Lock的對象調用了同步的方法。應該這樣處理,對象被鎖定/解鎖時使用acquire()/ release()方法而不是使用同步的方法。

(11).LI: Incorrect lazy initialization of static field (LI_LAZY_INIT_STATIC)

靜态域不正确的延遲初始化–

這種方法包含了一個不同步延遲初始化的非volatile靜态字段。因為編譯器或處理器可能會重新排列指令,如果該方法可以被多個線程調用,線程不能保證看到一個完全初始化的對象。你可以讓字段可變來解決此問題

(12).LI: Incorrect lazy initialization and update of static field (LI_LAZY_INIT_UPDATE_STATIC)

這種方法包含一個不同步延遲初始化的靜态字段。之後為字段指派,對象存儲到該位置後進一步更新或通路。字段後盡快讓其他線程能夠通路。如果該方法的進一步通路該字段為初始化對象提供服務,然後你有一個非常嚴重的多線程bug,除非别的東西阻止任何其他線程通路存儲的對象,直到它完全初始化。

即使你有信心,該方法是永遠不會被多個線程調用時,在它的值還沒有被充分初始化或移動,不把它設定為static字段時它可能會更好。

(13).ML: Method synchronizes on an updated field (ML_SYNC_ON_UPDATED_FIELD)

對象擷取一個可變字段時進行同步。這是沒有意義的,因為不同的線程可以在不同的對象同步。

(14).MSF: Mutable servlet field (MSF_MUTABLE_SERVLET_FIELD)

一個web服務一般隻能建立一個servlet或者jsp的執行個體(例如:treates是一個單利類),它會被多個線程調用這個執行個體的方法服務于多個同時的請求。是以使用易變的字段屬性産生競争的情況。

(15).MWN: Mismatched notify() (MWN_MISMATCHED_NOTIFY)

此方法調用Object.notify()或Object.notifyAll()而沒有擷取到該對象的對象鎖。調用notify()或notifyAll()而沒有持有該對象的對象鎖,将導緻IllegalMonitorStateException異常。

(16).MWN: Mismatched wait() (MWN_MISMATCHED_WAIT)

此方法調用Object.wait()而沒有擷取到該對象的對象鎖。調用wait()而沒有持有該對象的對象鎖,将導緻IllegalMonitorStateException異常。

(17).NP: Synchronize and null check on the same field. (NP_SYNC_AND_NULL_CHECK_FIELD)

如果代碼塊是同步的,那麼久不可能為空。如果是空,同步時就會抛出NullPointerException異常。最好是在另一個代碼塊中進行同步。

(18).No: Using notify() rather than notifyAll() (NO_NOTIFY_NOT_NOTIFYALL)

調用notify()而不是notifyAll()方法。 Java的監控器通常用于多個條件。調用notify()隻喚醒一個線程,這意味着該線程被喚醒隻是滿足的目前的唯一條件。

(19).RS: Class’s readObject() method is synchronized (RS_READOBJECT_SYNC)

序列化類中定義了同步的readObject()。通過定義,反序列化建立的對象隻有一個線程可以通路,是以沒有必要的readObject()進行同步。如果的readObject()方法本身造成對象對另一個線程可見,那麼這本身就是不好的編碼方式。

(20).Ru: Invokes run on a thread (did you mean to start it instead?) (RU_INVOKE_RUN)

這種方法顯式調用一個對象的run()。一般來說,類是實作Runnable接口的,因為在一個新的線程他們将有自己的run()方法,在這種情況下Thread.start()方法調用是正确的。

(21).SC: Constructor invokes Thread.start() (SC_START_IN_CTOR)

在構造函數中啟動一個線程。如果類曾經被子類擴充過,那麼這很可能是錯的,因為線程将在子類構造之前開始啟動。

(22).SP: Method spins on field (SP_SPIN_ON_FIELD)

方法無限循環讀取一個字段。編譯器可合法懸挂宣讀循環,變成一個無限循環的代碼。這個類應該改變,是以使用适當的同步(包括等待和通知要求)

(23).STCAL: Call to static Calendar (STCAL_INVOKE_ON_STATIC_CALENDAR_INSTANCE)

即使JavaDoc對此不包含暗示,而Calendars本身在多線程中使用就是不安全的。探測器發現當調用Calendars的執行個體時将會獲得一個靜态對象。

Calendar rightNow = Calendar.getInstance();

(24).STCAL: Call to static DateFormat (STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE)

在官方的JavaDoc,DateFormats多線程使用本事就是不安全的。探測器發現調用一個DateFormat的執行個體将會獲得一個靜态對象。

myString = DateFormat.getDateInstance().format(myDate);

(25).STCAL: Static Calendar (STCAL_STATIC_CALENDAR_INSTANCE)

Calendar在多線程中本身就是不安全的,如果線上程範圍中共享一個Calendarde 執行個體而不使用一個同步的方法在應用中就會出現一些奇怪的行為。在sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate()中會抛出ArrayIndexOutOfBoundsExceptions or IndexOutOfBoundsExceptions異常。

(26).STCAL: Static DateFormat (STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE)

DateFormat 在多線程中本身就是不安全的,如果線上程範圍中共享一個DateFormat的執行個體而不使用一個同步的方法在應用中就會出現一些奇怪的行為。

(27).SWL: Method calls Thread.sleep() with a lock held (SWL_SLEEP_WITH_LOCK_HELD)

當持有對象時調用Thread.sleep()。這可能會導緻很差的性能和可擴充性,或陷入死鎖,因為其他線程可能正在等待獲得鎖。調用wait()是一個更好的主意,釋放對象的持有以允許其他線程運作。

(28).UG: Unsynchronized get method, synchronized set method (UG_SYNC_SET_UNSYNC_GET)

這個類包含類似命名的get和set方法。在set方法是同步方法和get方法是非同步方法。這可能會導緻在運作時的不正确行為,因為調用的get方法不一定傳回對象一緻狀态。 GET方法應該同步。

(29).UL: Method does not release lock on all paths (UL_UNRELEASED_LOCK)

方法獲得了目前的對象所,但是在方法中始終沒有釋放它。一個正确的示例如下:

Lock l = …;

l.lock();

try {

// do something

} finally {

l.unlock();

}

(30).UL: Method does not release lock on all exception paths (UL_UNRELEASED_LOCK_EXCEPTION_PATH)

方法獲得了目前的對象所,但是在所有的異常進行中始終沒有釋放它。一個正确的示例如下:

Lock l = …;

l.lock();

try {

// do something

} finally {

l.unlock();

}

(31).UW: Unconditional wait (UW_UNCOND_WAIT)

方法中包含調用java.lang.Object.wait(),而卻沒有放到條件流程控制中。該代碼應确認條件尚未滿足之前等待;先前任何通知将被忽略。

(32).VO: A volatile reference to an array doesn’t treat the array elements as volatile (VO_VOLATILE_REFERENCE_TO_ARRAY)

聲明一個變量引用數組,這可能不是你想要的。如果一個變量引用數組,那麼對引用數組的讀和寫都是不安全的,但是數組元素不是變量。取得數組的變量值你可以使用java.util.concurrent包中的數組的原子性特性

(33).WL: Sychronization on getClass rather than class literal (WL_USING_GETCLASS_RATHER_THAN_CLASS_LITERAL)

執行個體的方法中同步this.getClass(),如果這個類有子類集合,那麼子類集合中的對象将會在這個類的各個子類上進行同步,這不是我們想要的效果,我們隻要同步目前的類對象而不包含它的所有子類,可以同步類名.getClass()。例如,java.awt.Label的代碼:

private static final String base = “label”;

private static int nameCounter = 0;

String constructComponentName() {

synchronized (getClass()) {

return base + nameCounter++;

}

}

Label中的子類集合不可能在同一個子對象上進行同步,替換上面的方法為:

private static final String base = “label”;

private static int nameCounter = 0;

String constructComponentName() {

synchronized (Label.class) {

return base + nameCounter++;

}

}

(34).WS: Class’s writeObject() method is synchronized but nothing else is (WS_WRITEOBJECT_SYNC)

這個類有一個writeObject()方法是同步的,但是這個類中沒有其他的同步方法。

(35).Wa: Condition.await() not in loop (WA_AWAIT_NOT_IN_LOOP)

方法沒有在循環中調用java.util.concurrent.await()。如果對象是用于多種條件,打算調用wait()方法的條件可能不是實際發生的。

(36).Wa: Wait not in loop (WA_NOT_IN_LOOP)

這種方法包含調用java.lang.Object.wait(),而這并不是一個循環。如果螢幕用于多個條件,打算調用wait()方法的條件可能不是實際發生的。

8:Malicious codevulnerability關于惡意破壞代碼相關方面的

(1).EI: May expose internal representation by returning reference to mutable object (EI_EXPOSE_REP)

傳回一個易變對象引用并把它儲存在對象字段中時會暴露對象内部的字段描述,如果接受不守信任的代碼通路或者沒有檢查就去改變易變對象的會涉及對象的安全和其他重要屬性的安全。傳回一個對象的新副本,在很多情況下更好的辦法。

(2).EI2: May expose internal representation by incorporating reference to mutable object (EI_EXPOSE_REP2)

此代碼把外部可變對象引用存儲到對象的内部表示。如果執行個體受到不信任的代碼的通路和沒有檢查的變化危及對象和重要屬性的安全。存儲一個對象的副本,在很多情況下是更好的辦法。

(3).FI: Finalizer should be protected, not public (FI_PUBLIC_SHOULD_BE_PROTECTED)

一個類中的finalize()方法必須聲明為protected,而不能為public類型

(4).MS: Public static method may expose internal representation by returning array (MS_EXPOSE_REP)

一個public類型的靜态方法傳回一個數組,可能引用内部屬性的暴露。任何代碼調用此方法都可以自由修改底層數組。一個解決辦法是傳回一個數組的副本。

(5).MS: Field should be both final and package protected (MS_FINAL_PKGPROTECT)

一個靜态字段可能被惡意代碼或另外一個包所改變的。字段可以放到protected包中也可以定義為final類型的以避免此問題。

(6).MS: Field is a mutable array (MS_MUTABLE_ARRAY)

一個定義為final類型的靜态字段引用一個數組時它可以被惡意代碼或在另其他包中所使用。這些代碼可以自由修改數組的内容。

(7).MS: Field is a mutable Hashtable (MS_MUTABLE_HASHTABLE)

一個定義為final類型的靜态字段引用一個Hashtable時可以被惡意代碼或者在其他包中被調用,這些方法可以修改Hashtable的值。

(8).MS: Field should be moved out of an interface and made package protected (MS_OOI_PKGPROTECT)

将域盡量不要定義在接口中,并聲明為包保護

在接口中定義了一個final類型的靜态字段,如數組或哈希表等易變對象。這些對象可以被惡意代碼或者在其他包中被調用,為了解決這個問題,需要把它定義到一個具體的實體類中并且聲明為保護類型以避免這種錯誤。

(9).MS: Field should be package protected (MS_PKGPROTECT)

一個靜态字段是可以改變的惡意代碼或其他的包通路修改。可以把這種類型的字段聲明為final類型的以防止這種錯誤。

9:Dodgy關于代碼運作期安全方面的

(1).XSS: Servlet reflected cross site scripting vulnerability (XSS_REQUEST_PARAMETER_TO_SEND_ERROR)

在代碼中在Servlet輸出中直接寫入一個HTTP參數,這會造成一個跨站點的腳本漏洞。

(2).XSS: Servlet reflected cross site scripting vulnerability (XSS_REQUEST_PARAMETER_TO_SERVLET_WRITER)

代碼直接寫入參數的HTTP伺服器錯誤頁(使用HttpServletResponse.sendError)。表達了類似的不受信任的輸入會引起跨站點腳本漏洞。

(3).BC: Questionable cast to abstract collection (BC_BAD_CAST_TO_ABSTRACT_COLLECTION)

在代碼投把一個集合強制類型轉換為一個抽象的集合(如list,set或map)。保證該對象類型和将要轉換的類型是一緻的。如果你隻是想要便利一個集合,那麼你就不必将它轉換為Set或List。

(4).BC: Questionable cast to concrete collection (BC_BAD_CAST_TO_CONCRETE_COLLECTION)

代碼把抽象的集合(如List,Set,或Collection)強制轉換為具體落實類型(如一個ArrayList或HashSet)。這可能不正确,也可能使您的代碼很脆弱,因為它使得難以在今後的切換指向其他具體實作。除非你有特别理由這樣做,否則隻需要使用抽象的集合類。

(5).BC: Unchecked/unconfirmed cast (BC_UNCONFIRMED_CAST)

強制類型轉換操作沒有經過驗證,而且不是所有的此種類型裝換過的類都可以再強制類型轉換為原類型。在代碼中需要進行邏輯判斷以保證可以進行這樣的操作。

(6).BC: instanceof will always return true (BC_VACUOUS_INSTANCEOF)

instanceof測試将始終傳回真(除非被測試的值為空)。雖然這是安全,確定它是不是說明一些誤解或其他一些邏輯錯誤。如果你真的想測試是空的價值,也許會更清楚這樣做的更好空試驗,而不是一個instanceof測試。

(7).BSHIFT: Unsigned right shift cast to short/byte (ICAST_QUESTIONABLE_UNSIGNED_RIGHT_SHIFT)

無符号數右移後進行轉換為short或者byte類型時可能會丢棄掉高位的值,這樣的結果就是有符合數和無符号數無法區分(這取決于移位大小)

(8).CI: Class is final but declares protected field (CI_CONFUSED_INHERITANCE)

這個類被聲明為final的,而是字段屬性卻聲明為保護類型的。由于是final類,它不能再被繼承,而再聲明為保護類型的很容易造成混淆。為了從外部能正确的使用它應該把它們聲明為private或者public類型。

(9).DB: Method uses the same code for two branches (DB_DUPLICATE_BRANCHES)

此方法使用相同的代碼,以實作兩個有條件的分支。檢查以確定這是不是一個編碼錯誤。

(10).DB: Method uses the same code for two switch clauses (DB_DUPLICATE_SWITCH_CLAUSES)

他的方法使用相同的代碼來實作兩個switch的聲明條款。這可能是重複代碼的情況,但可能也顯示出編碼的錯誤。

(11).DLS: Dead store to local variable (DLS_DEAD_LOCAL_STORE)

該指令為局部變量指派,但在其後的沒有對她做任何使用。通常,這表明一個錯誤,因為值從未使用過。

(12).DLS: Useless assignment in return statement (DLS_DEAD_LOCAL_STORE_IN_RETURN)

本聲明把一個局部變量放到方法的傳回語句中。這對于方法中局部變量來說是沒有意思的。

(13).DLS: Dead store of null to local variable (DLS_DEAD_LOCAL_STORE_OF_NULL)

把一個本地變量指派為null值,并且再也沒有對這個變量做任何的操作。這樣可能是為了垃圾回收,而是Java SE 6.0,這已不再需要。

(14).DMI: Code contains a hard coded reference to an absolute pathname (DMI_HARDCODED_ABSOLUTE_FILENAME)

此代碼包含檔案對象為一個絕對路徑名(例如,新的檔案(“/ home/dannyc/workspace/j2ee/src/share/com/sun/enterprise/deployment”);

(15).DMI: Non serializable object written to ObjectOutput (DMI_NONSERIALIZABLE_OBJECT_WRITTEN)

代碼中讓一個非序列化的對象出現在ObjectOutput.writeObject()方法中,這樣會引起一個錯誤。

(16).DMI: Invocation of substring(0), which returns the original value (DMI_USELESS_SUBSTRING)

此代碼調用了subString(0)方法,它将傳回原來的值。

(17).Eq: Class doesn’t override equals in superclass (EQ_DOESNT_OVERRIDE_EQUALS)

子類定義了一個新的equals方法但是卻不是覆寫了父類本省的equals()方法。

(18).FE: Test for floating point equality (FE_FLOATING_POINT_EQUALITY)

此操作比較兩個浮點值是否相等。由于浮點運算可能會涉及到舍入,計算float和double值可能不準确。如果要求值必須準确,如貨币值,可以考慮使用固定精度類型,如BigDecimal類型的值來比較

(19).FS: Non-Boolean argument formatted using %b format specifier (VA_FORMAT_STRING_BAD_CONVERSION_TO_BOOLEAN)

使用%b去格式化Boolean類型的值不正确的但是它不會抛出異常,任何非空的值都會輸出true,任何為空的值都會輸出false

(20).IC: Initialization circularity (IC_INIT_CIRCULARITY)

在引用兩個互相調用為環狀static方法去初始化一個執行個體時是錯誤的。

(21).ICAST: integral division result cast to double or float (ICAST_IDIV_CAST_TO_DOUBLE)

整形數除法強制轉換為double或者float類型。

int x = 2;

int y = 5;

// Wrong: yields result 0.0

double value1 = x / y;

// Right: yields result 0.4

double value2 = x / (double) y;

(22).ICAST: Result of integer multiplication cast to long (ICAST_INTEGER_MULTIPLY_CAST_TO_LONG)

整形數做乘法運算結果轉換為long值時如果采用

long convertDaysToMilliseconds(int days) { return 1000*3600*24*days; } 結果會因為超出整形的範圍而出錯。

如果使用:

long convertDaysToMilliseconds(int days) { return 1000L*3600*24*days; }

或者:

static final long MILLISECONDS_PER_DAY = 24L*3600*1000;

long convertDaysToMilliseconds(int days) { return days * MILLISECONDS_PER_DAY; }

都可以避免此問題。

(23).IM: Computation of average could overflow (IM_AVERAGE_COMPUTATION_COULD_OVERFLOW)

代碼中使用x % 2 == 1的方法去驗證運算是否存在餘數的情況,但是如果出現負數的情況就不起作用了。使用x & 1 == 1, or x % 2 != 0來代替

(24).INT: Vacuous comparison of integer value (INT_VACUOUS_COMPARISON)

整形數進行比較結果總是不變。例如:x <= Integer.MAX_VALUE

(25).MTIA: Class extends Servlet class and uses instance variables (MTIA_SUSPECT_SERVLET_INSTANCE_FIELD)

這個類擴充從Servlet類,并使用執行個體的成員變量。由于隻有一個Servlet類的執行個體,并在多線程方式使用,這種模式有可能存在問題。考慮隻使用方法的局部變量。

(26).MTIA: Class extends Struts Action class and uses instance variables (MTIA_SUSPECT_STRUTS_INSTANCE_FIELD)

類擴充自Struts的Action類并使用這個執行個體的成員變量,因為在Struts架構中隻存在一個Action執行個體對象并且使用在多線程的情況下很可能會出現問題。

(27).NP: Dereference of the result of readLine() without nullcheck (NP_DEREFERENCE_OF_READLINE_VALUE)

對readLine()的結果值沒有進行判空操作就去重新指派,這樣的操作可以會抛出空指針異常。

(28).NP: Immediate dereference of the result of readLine() (NP_IMMEDIATE_DEREFERENCE_OF_READLINE)

對readLine()的結果立即指派,這樣的操作可以會抛出空指針異常。

(29).NP: Possible null pointer dereference due to return value of called method (NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE)

方法的傳回值沒有進行是否為空的檢查就重新指派,這樣可能會出現空指針異常。

(30).NP: Parameter must be nonnull but is marked as nullable (NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE)

參數值在任何情況下都不能為空,但是有明确的注釋它可以為空。

(31).NS: Potentially dangerous use of non-short-circuit logic (NS_DANGEROUS_NON_SHORT_CIRCUIT)

代碼中使用(& or |)代替(&& or ||)操作,這會造成潛在的危險。

(32).NS: Questionable use of non-short-circuit logic (NS_NON_SHORT_CIRCUIT)

代碼中使用(& or |)代替(&& or ||)操作,會引起不安全的操作

(33).PZLA: Consider returning a zero length array rather than null (PZLA_PREFER_ZERO_LENGTH_ARRAYS)

考慮傳回一個零長度的數組,而不是null值

(34).QF: Complicated, subtle or wrong increment in for-loop (QF_QUESTIONABLE_FOR_LOOP)

确定這個循環是正确的變量遞增,看起來,另一個變量被初始化,檢查的循環。這是由于for循環中太複雜的定義造成的。

(35).RCN: Redundant comparison of non-null value to null (RCN_REDUNDANT_COMPARISON_OF_NULL_AND_NONNULL_VALUE)

方法中包含一個不能為空的指派還包含一個可以為空的指派。備援比較非空值為空。

(36).RCN: Redundant comparison of two null values (RCN_REDUNDANT_COMPARISON_TWO_NULL_VALUES)

方法中對兩個null值進行比較

(37).RCN: Redundant nullcheck of value known to be non-null (RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE)

方法中對不為空的值進行為空的判斷。

(38).REC: Exception is caught when Exception is not thrown (REC_CATCH_EXCEPTION)

在try/catch塊中捕獲異常,但是異常沒有在try語句中抛出而RuntimeException又沒有明确的被捕獲

(39).RI: Class implements same interface as superclass (RI_REDUNDANT_INTERFACES)

子類和父類都實作了同一個接口,這種定義是多餘的。

(40).RV: Method discards result of readLine after checking if it is nonnull (RV_DONT_JUST_NULL_CHECK_READLINE)

readLine方法的結果不為空時被抛棄

(41).RV: Remainder of 32-bit signed random integer (RV_REM_OF_RANDOM_INT)

此代碼生成一個随機的符号整數,然後計算另一個值的。由于随機數可以是負數,是以其餘操作的結果也可以是負面的。考慮使用Random.nextInt(int)方法代替。

(42).SA: Double assignment of local variable (SA_LOCAL_DOUBLE_ASSIGNMENT)

為一個局部變量兩次指派,這樣是沒有意義的。例如:

public void foo() {

int x,y;

x = x = 17;

}

(43).SA: Self assignment of local variable (SA_LOCAL_SELF_ASSIGNMENT)

局部變量使用自身給自己指派

public void foo() {

int x = 3;

x = x;

}

(44).SF: Switch statement found where one case falls through to the next case (SF_SWITCH_FALLTHROUGH)

Switch語句中一個分支執行後又執行了下一個分支。通常case後面要跟break 或者return語句來跳出。

(45).SF: Switch statement found where default case is missing (SF_SWITCH_NO_DEFAULT)

Switch沒有預設情況下執行的case語句。

(46).Se: private readResolve method not inherited by subclasses (SE_PRIVATE_READ_RESOLVE_NOT_INHERITED)

聲明為private的序列化方法被子類繼承

(47).UCF: Useless control flow (UCF_USELESS_CONTROL_FLOW)

沒有任何作用的條件語句。

if (argv.length == 0) {

// TODO: handle this case

}

(48).UCF: Useless control flow to next line (UCF_USELESS_CONTROL_FLOW_NEXT_LINE)

無效的條件控制語句,注意if (argv.length == 1);以“;”結尾,下面的語句無論是否滿足都會運作。

if (argv.length == 1);

System.out.println(“Hello, ” + argv[0]);

(49).UwF: Field not initialized in constructor (UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR)

字段從來沒有在任何構造函數初始化,對象被建立後值為空。如果該字段未被定義就重新指派會産生一個空指針異常。

(50).XFB: Method directly allocates a specific implementation of xml interfaces (XFB_XML_FACTORY_BYPASS)

方法自定義了一種XML接口的實作類。最好是使用官方提供的工廠類來建立這些對象,以便可以在運作期中改變。例如:

javax.xml.parsers.DocumentBuilderFactory

javax.xml.parsers.SAXParserFactory

javax.xml.transform.TransformerFactory

org.w3c.dom.Document.createXXXX

繼續閱讀