靜態(tài)分析工具及使用總結(jié)(三)
Posted on 2007-01-28 22:46 繁星滿(mǎn)空 閱讀(3034) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): Java
靜態(tài)分析工具及使用總結(jié)(三)
這里主要介紹三種開(kāi)源的工具,PMD、CheckStyle和FindBugs,著重是在Ant里的調(diào)用,據(jù)說(shuō)商業(yè)軟件JTest也是著名的代碼分析工具,哈哈,要花錢(qián)的沒(méi)有用過(guò)。
FindBugs(http://findbugs.sourceforge.net/)版本
簡(jiǎn)介:findbugs
是一個(gè)在java程序中查找bug的程序,它查找bug模式的實(shí)例,也就是
可能出錯(cuò)的代碼實(shí)例,
?????? 注意findbugs是檢查java字節(jié)碼,也就是*.class文件。
用法:在圖形界面下使用findbugs,可以新建一個(gè)工程,設(shè)置類(lèi)的路徑和源代碼的路徑,
詳細(xì)的文檔請(qǐng)參考官方文檔。
?????? 下面主要介紹在Ant里的調(diào)用。
? 下面是build.xml的相關(guān)配置:



</ path >
< taskdef? name ="findbugs" ?classname ="edu.umd.cs.findbugs.anttask.FindBugsTask" ?classpathref ="findbugs.path" />
<!-- ?以上定義findbugs的task? -->

< property? name ="findbugs.home" ?value ="${lib.dir}/findbugs-1.1.1" ? />
<!-- ?定義findbugs的home,findbugs的task要使用? -->

?< target? name ="findbugs" >









????? 其中的${lib.dir}\findbugs-
使用過(guò)濾器我們就可以定義使用哪些bug檢測(cè)器和針對(duì)哪些類(lèi)進(jìn)行檢查,因?yàn)橐坏?/font>
項(xiàng)目比較龐大,
????? 那查看冗長(zhǎng)的bug報(bào)告也是十分痛苦的事情。















自帶檢測(cè)器的介紹:
findbugs
自帶60余種Bad practice,80余種Correntness,1種
Internationalization
,
??? 12種Malicious code vulnerability,27種Multithreaded correntness,23種Performance,43種Dodgy。
Bad practice
壞的實(shí)踐
一些不好的實(shí)踐,下面列舉幾個(gè):
HE
:
類(lèi)定義了equals(),卻沒(méi)有hashCode();或類(lèi)定義了equals(),卻使用Object. hashCode();或類(lèi)定義了hashCode(),卻沒(méi)有equals();或類(lèi)定義了hashCode(),卻使用Object.equals();類(lèi)繼承了equals(),卻使用Object.hashCode()。
SQL
:
Statement
的execute方法調(diào)用了非常量的字符串;或Prepared Statement是由一個(gè)非常量的字符串產(chǎn)生。
DE
:
方法終止或不處理異常,一般情況下,異常應(yīng)該被處理或報(bào)告,或被方法拋出。
Correctness
一般的正確性問(wèn)題
可能導(dǎo)致錯(cuò)誤的代碼,下面列舉幾個(gè):
NP
:
空指針被引用;在方法的異常路徑里,空指針被引用;方法沒(méi)有檢查參數(shù)是否null;null值產(chǎn)生并被引用;null值產(chǎn)生并在方法的異常路徑被引用;傳給方法一個(gè)聲明為@NonNull的null參數(shù);方法的返回值聲明為@NonNull實(shí)際是null。
Nm
:
類(lèi)定義了hashcode()方法,但實(shí)際上并未覆蓋父類(lèi)Object的hashCode();類(lèi)定義了tostring()方法,但實(shí)際上并未覆蓋父類(lèi)Object的toString();很明顯的方法和構(gòu)造器混淆;方法名容易混淆。
SQL
:
方法嘗試訪問(wèn)一個(gè)Prepared Statement的0索引;方法嘗試訪問(wèn)一個(gè)ResultSet的0索引。
UwF
:
所有的write都把屬性置成null,這樣所有的讀取都是null,這樣這個(gè)屬性是否有必要存在;或?qū)傩詮臎](méi)有被write。
Internationalization
國(guó)際化
當(dāng)對(duì)字符串使用upper或lowercase方法,如果是國(guó)際的字符串,可能會(huì)不恰當(dāng)?shù)霓D(zhuǎn)換。
????
???Malicious code vulnerability
可能受到的惡意攻擊
???
如果代碼公開(kāi),可能受到惡意攻擊的代碼,下面列舉幾個(gè):
??? FI
:
一個(gè)類(lèi)的finalize()應(yīng)該是protected,而不是public的。
???
MS
:
屬性是可變的數(shù)組;屬性是可變的Hashtable;屬性應(yīng)該是package protected的。
???
???Multithreaded correctness
多線(xiàn)程的正確性
???
多線(xiàn)程編程時(shí),可能導(dǎo)致錯(cuò)誤的代碼,下面列舉幾個(gè):
???
ESync
:
空的同步塊,很難被正確使用。
???
MWN
:
錯(cuò)誤使用notify(),可能導(dǎo)致IllegalMonitorStateException異常;或錯(cuò)誤的
使用wait()。
No
:
使用notify()而不是notifyAll(),只是喚醒一個(gè)線(xiàn)程而不是所有等待的線(xiàn)程。
SC
:
構(gòu)造器調(diào)用了Thread.start(),當(dāng)該類(lèi)被繼承可能會(huì)導(dǎo)致錯(cuò)誤。
???
???
Performance
性能問(wèn)題
???
可能性能不佳的代碼,下面列舉幾個(gè):
???
DM
:
方法調(diào)用了低效的Boolean的構(gòu)造器,而應(yīng)該用Boolean.valueOf(…);用類(lèi)似
Integer.toString(1)
代替new Integer(1).toString();方法調(diào)用了低效的float的構(gòu)造器,應(yīng)該用靜態(tài)的valueOf方法。
SIC
:
如果一個(gè)內(nèi)部類(lèi)想在更廣泛的地方被引用,它應(yīng)該聲明為static。
SS
:
如果一個(gè)實(shí)例屬性不被讀取,考慮聲明為static。
UrF
:
如果一個(gè)屬性從沒(méi)有被read,考慮從類(lèi)中去掉。
UuF
:
如果一個(gè)屬性從沒(méi)有被使用,考慮從類(lèi)中去掉。
???
??? Dodgy
危險(xiǎn)的
???
具有潛在危險(xiǎn)的代碼,可能運(yùn)行期產(chǎn)生錯(cuò)誤,下面列舉幾個(gè):
???
BC
:
對(duì)抽象集合如List、Set的造型;對(duì)具體集合如ArrayList、HashSet的造型;
未檢查或無(wú)法保證的造型;
CI
:
類(lèi)聲明為final但聲明了protected的屬性。
DLS
:
對(duì)一個(gè)本地變量賦值,但卻沒(méi)有讀取該本地變量;本地變量賦值成null,卻沒(méi)有讀取該本地變量。
ICAST
:
整型數(shù)字相乘結(jié)果轉(zhuǎn)化為長(zhǎng)整型數(shù)字,應(yīng)該將整型先轉(zhuǎn)化為長(zhǎng)整型數(shù)字再相乘。
INT
:
沒(méi)必要的整型數(shù)字比較,如X <= Integer.MAX_VALUE。
NP
:
對(duì)readline()的直接引用,而沒(méi)有判斷是否null;對(duì)方法調(diào)用的直接引用,而方法可能返回null。
REC
:
直接捕獲Exception,而實(shí)際上可能時(shí)RuntimeException。
ST
:
從實(shí)例方法里直接修改類(lèi)變量,即static屬性。
自定義檢測(cè)器:
findbugs
提供了強(qiáng)大的自定義檢測(cè)器的功能,首先我們應(yīng)該清楚需要
檢查的案例,findbugs的官方文檔里并沒(méi)有詳細(xì)的介紹如何自定義,那我們只能直接閱讀它的源碼了,著重閱讀BytecodeScanningDetector和ByteCodePatternDetector的子類(lèi)型,它們可以檢測(cè)一般類(lèi)型的問(wèn)題。Findbugs利用了Byte Code Engineering Library(即BCEL,Apache上的一個(gè)開(kāi)源項(xiàng)目),以實(shí)現(xiàn)其檢測(cè)器,所有的字節(jié)碼掃描都是基于visitor模式。我們可以參照findbugs自帶的檢測(cè)器的類(lèi)的源碼,去編寫(xiě)一個(gè)自定義的檢測(cè)器代碼,編寫(xiě)完后編譯成類(lèi)文件,同時(shí)我們還需要提供兩個(gè)XML文件,Findbugs.xml和message.xml,在Findbugs.xml里指定檢測(cè)器和實(shí)現(xiàn)類(lèi),檢測(cè)器的縮寫(xiě)、類(lèi)型如快速或慢速,而message文件里則包括了該檢測(cè)器的描述信息,可能是html的,然后將源文件、類(lèi)文件和上面兩個(gè)XML文件打包成jar文件,放在findbugs home的plugin文件夾下,這樣我們就可以使用自定義檢查器了。
參考文檔:
FindBugs
官方文檔(http://findbugs.sourceforge.net/)
FindBugs
,第 1 部分: 提高代碼質(zhì)量
http://www-128.ibm.com/developerworks/cn/java/j-findbug1/
FindBugs
,第 2 部分: 編寫(xiě)自定義檢測(cè)器
http://www-128.ibm.com/developerworks/cn/java/j-findbug2/