posts - 11, comments - 10, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          靜態(tài)分析工具及使用總結(jié)(三)

          Posted on 2007-01-28 22:46 繁星滿(mǎn)空 閱讀(3034) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Java

          靜態(tài)分析工具及使用總結(jié)(三)

          ?

          這里主要介紹三種開(kāi)源的工具,PMDCheckStyleFindBugs,著重是在Ant里的調(diào)用,據(jù)說(shuō)商業(yè)軟件JTest也是著名的代碼分析工具,哈哈,要花錢(qián)的沒(méi)有用過(guò)。

          ?

          FindBugs(http://findbugs.sourceforge.net/)版本1.1.1

          簡(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? id ="findbugs.path" >
          ???<
          fileset? dir ="${lib.dir}/findbugs-1.1.1" >
          ???????<
          include? name ="**/*.jar" ? />
          ???</
          fileset >
          </
          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" >
          ????<
          findbugs? home ="${findbugs.home}" ?includeFilter? =?"${lib.dir}\findbugs-1.1.1\?plugin\filter.xml" ?output ="html" ?outputFile ="d:\test.html" ? >
          ????????<
          class? location ="${class.dir}/classes/?" ? />
          ????????<!--
          ?以上定義findbugs查找的類(lèi)路徑? -->
          ????????<
          auxClasspath? refid ="classpath" />
          ????????<!--
          ?以上定義上述類(lèi)所依賴(lài)的類(lèi)路徑? -->
          ????????<
          sourcePath? path ="${src.dir}" ? />
          ????????<!--
          ?以上定義源代碼的路徑? -->
          ????</
          findbugs >
          </
          target >


          ????? 其中的${lib.dir}\findbugs-1.1.1\ plugin\filter.xml配置文件的內(nèi)容如下:

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

          < FindBugsFilter >
          ????
          <!-- ?該類(lèi)使用所有的bug檢測(cè)器? -->
          ????
          < Match? class ="com.foobar.AClass" > ????
          ????
          <!-- ?該類(lèi)使用bugcode為HE的檢測(cè)器? -->
          ????
          < Match? class ="com.foobar.BClass" >
          ????????
          < BugCode? name ="HE" ? />
          ????
          </ Match >
          ????
          <!-- ?該類(lèi)的AMethod和BMethod方法使用bugcode為HE的檢測(cè)器? -->
          ????
          < Match? class ="com.foobar.CClass" >
          ????????
          < Or >
          ????????????
          < Method? name ="AMethod" />
          ????????????
          < Method? name ="BMethod" />
          ????????
          </ Or >
          ????????
          < BugCode? name ="HE" />
          ????
          </ Match >
          ?
          </ FindBugsFilter >

          自帶檢測(cè)器的介紹: findbugs 自帶60余種Bad practice80余種Correntness1 Internationalization
          ??? 12Malicious code vulnerability27Multithreaded correntness23Performance43Dodgy


          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ù)是否nullnull值產(chǎn)生并被引用;null值產(chǎn)生并在方法的異常路徑被引用;傳給方法一個(gè)聲明為@NonNullnull參數(shù);方法的返回值聲明為@NonNull實(shí)際是null

          Nm 類(lèi)定義了hashcode()方法,但實(shí)際上并未覆蓋父類(lèi)ObjecthashCode();類(lèi)定義了tostring()方法,但實(shí)際上并未覆蓋父類(lèi)ObjecttoString();很明顯的方法和構(gòu)造器混淆;方法名容易混淆。

          SQL 方法嘗試訪問(wèn)一個(gè)Prepared Statement0索引;方法嘗試訪問(wèn)一個(gè)ResultSet0索引。

          UwF 所有的write都把屬性置成null,這樣所有的讀取都是null,這樣這個(gè)屬性是否有必要存在;或?qū)傩詮臎](méi)有被write


          Internationalization
          國(guó)際化

          當(dāng)對(duì)字符串使用upperlowercase方法,如果是國(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ì)抽象集合如ListSet的造型;對(duì)具體集合如ArrayListHashSet的造型;

          未檢查或無(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ì)的介紹如何自定義,那我們只能直接閱讀它的源碼了,著重閱讀BytecodeScanningDetectorByteCodePatternDetector的子類(lèi)型,它們可以檢測(cè)一般類(lèi)型的問(wèn)題。Findbugs利用了Byte Code Engineering Library(即BCELApache上的一個(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.xmlmessage.xml,在Findbugs.xml里指定檢測(cè)器和實(shí)現(xiàn)類(lèi),檢測(cè)器的縮寫(xiě)、類(lèi)型如快速或慢速,而message文件里則包括了該檢測(cè)器的描述信息,可能是html的,然后將源文件、類(lèi)文件和上面兩個(gè)XML文件打包成jar文件,放在findbugs homeplugin文件夾下,這樣我們就可以使用自定義檢查器了。

          ?

          參考文檔:

          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/

          代碼靜態(tài)分析(http://blog.donews.com/foxgem/archive/2005/04/23/347444.aspx
          主站蜘蛛池模板: 修文县| 镇平县| 安庆市| 中西区| 皋兰县| 新沂市| 鹤山市| 鱼台县| 龙江县| 璧山县| 乌审旗| 开江县| 韩城市| 阿勒泰市| 乐平市| 六安市| 鸡西市| 潼关县| 临颍县| 孝感市| 开封县| 旬邑县| 轮台县| 宁强县| 泌阳县| 隆化县| 海安县| 班戈县| 铜鼓县| 凤冈县| 行唐县| 宜兰市| 北海市| 二手房| 桑植县| 泸西县| 社会| 集贤县| 屏南县| 淳安县| 横峰县|