天天看點

性能優化總結1:findbugs :的使用

Findbugs

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

以下是findbugs的面闆

性能優化總結1:findbugs :的使用

performance:性能

dodgy code: 不符合規範的代碼

multithreaded correctness: 多線程相關

correctness:代碼的正确性

security:安全性

bad practice: 不好的習慣

experimental: 實驗性問題

internationalization:國際化問題

malicious code vulnerability: 惡意代碼

findbugs右側面闆:

性能優化總結1:findbugs :的使用

priority代表了嚴重等級,紅色最嚴重,是以我們可以重點關注一下紅色。下方是錯誤詳情。

Bad practice 壞的實踐

一些不好的實踐,下面列舉幾個:

1、類定義了equals(),卻沒有hashCode();。

2、:Statement 的execute方法調用了非常量的字元串;或Prepared Statement是由一個非常量的字元串産生。

3、: 方法終止或不處理異常,一般情況下,異常應該被處理或報告,或被方法抛出。

Correctness 一般的正确性問題

可能導緻錯誤的代碼,下面列舉幾個:

1、: 空指針被引用;在方法的異常路徑裡,空指針被引用;方法沒有檢查參數是否null;null值産生并被引用;null值産生并在方法的異常路徑被引用;傳給方法一個聲明為@NonNull的null參數;方法的傳回值聲明為@NonNull實際是null。

2、: 類定義了hashcode()方法,但實際上并未覆寫父類Object的hashCode();類定義了tostring()方法,但實際上并未覆寫父類Object的toString();很明顯的方法和構造器混淆;方法名容易混淆。

3、:方法嘗試通路一個Prepared Statement的0索引;方法嘗試通路一個ResultSet的0索引。

4、:所有的write都把屬性置成null,這樣所有的讀取都是null,這樣這個屬性是否有必要存在;或屬性從沒有被write。

Internationalization 國際化

當對字元串使用upper或lowercase方法,如果是國際的字元串,可能會不恰當的轉換。

Malicious code vulnerability 惡意代碼

如果代碼公開,可能受到惡意攻擊的代碼,下面列舉幾個:

1、: 一個類的finalize()應該是protected,而不是public的。

2、:屬性是可變的數組;屬性是可變的Hashtable;屬性應該是package protected的。

Multithreaded correctness 多線程的正确性

多線程程式設計時,可能導緻錯誤的代碼,下面列舉幾個:

1、ESync:空的同步塊,很難被正确使用。

2、MWN:錯誤使用notify(),可能導緻IllegalMonitorStateException異常;或錯誤的

使用wait()。

3、: 使用notify()而不是notifyAll(),隻是喚醒一個線程而不是所有等待的線程。

4、: 構造器調用了Thread.start(),當該類被繼承可能會導緻錯誤。

Performance 性能問題

可能導緻性能不佳的代碼,下面列舉幾個:

1、DM:方法調用了低效的Boolean的構造器,而應該用Boolean.valueOf(…);用類似

Integer.toString(1) 代替new Integer(1).toString();方法調用了低效的float的構造器,應該用靜态的valueOf方法。

2、SIC:如果一個内部類想在更廣泛的地方被引用,它應該聲明為static。

3、SS: 如果一個執行個體屬性不被讀取,考慮聲明為static。

4、UrF:如果一個屬性從沒有被read,考慮從類中去掉。

5、UuF:如果一個屬性從沒有被使用,考慮從類中去掉。

Dodgy 不符合規範的,有潛在危險的

具有潛在危險的代碼,可能運作期産生錯誤,下面列舉幾個:

1、CI: 類聲明為final但聲明了protected的屬性。

2、DLS:對一個本地變量指派,但卻沒有讀取該本地變量;本地變量指派成null,卻沒有讀取該本地變量。

3、ICAST: 整型數字相乘結果轉化為長整型數字,應該将整型先轉化為長整型數字再相乘。

4、INT:沒必要的整型數字比較,如X <= Integer.MAX_VALUE。

5、NP: 對readline()的直接引用,而沒有判斷是否null;對方法調用的直接引用,而方法可能傳回null。

6、REC:直接捕獲Exception,而實際上可能是RuntimeException。

7、ST: 從執行個體方法裡直接修改類變量,即static屬性。

舉幾個常見的例子:

bad practice:

1、傳回值沒有檢查的

例:

File f = new File(path + “/capture.json”);

f.delete();

public boolean delete() {

SecurityManager security = System.getSecurityManager();

if (security != null) {

security.checkDelete(path);

}

if (isInvalid()) {

return false;

}

return fs.delete(this);

}

類似的還有:f.createNewFile();f.mkdirs();f.setLastModified(currentTime);

f.renameTo(journalFile);等,在使用系統的一些api的時候一定要檢查是否有傳回值,然後根據傳回值判斷是否操作成功。

2、流沒有關閉的

所有的流都要在finally塊裡關閉,以確定不會出現記憶體洩漏

例:

try {

BufferedReader bf = new BufferedReader(new InputStreamReader(

mContext.getAssets().open(fileName)));

String line;

while ((line = bf.readLine()) != null) {

stringBuilder.append(line);

}

} catch (IOException e) {

e.printStackTrace();

}

這樣是不規範的,應該如下:

try {

bf = new BufferedReader(new InputStreamReader(

mContext.getAssets().open(fileName)));

String line;

while ((line = bf.readLine()) != null) {

stringBuilder.append(line);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (bf!=null){

try {

bf.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

3、定義了equals卻沒有定義hascode

如圖:

性能優化總結1:findbugs :的使用

4、字元串比較要用equals而不是等于号 ==

5、序列化的類裡面定義了一個非序列化的字段,沒有定義序列化ID

public class SaveCoverInfo implements Serializable {

private static final long serialVersionUID = 1L;

private String apiVersion;

private DataBean data;

public String getApiVersion() {
    return apiVersion;
}

public void setApiVersion(String apiVersion) {
    this.apiVersion = apiVersion;
}

public DataBean getData() {
    return data;
}

public void setData(DataBean data) {
    this.data = data;
}

public static class DataBean implements Serializable{
 
    private String img1;

    public String getImg1() {
        return img1;
    }

    public void setImg1(String img1) {
        this.img1 = img1;
    }
}
           

}

6、get/set方法沒有用到的

7、調用parsexxx比valueof效率高:

long date = Long.valueOf(dataMap.get(columnName));

應該寫成:

long date = Long.parseLong(dataMap.get(columnName));

8、頻繁裝箱拆箱的

public Boolean getFieldValue(String fieldStringValue) {

if (TextUtils.isEmpty(fieldStringValue)) return null;

return fieldStringValue.length() == 1 ? “1”.equals(fieldStringValue) : Boolean.valueOf(fieldStringValue);

}

9、使用對象前沒有判斷空指針的

10、switch語句沒有定義default的

還有很多其它類型的優化建議,就不再舉例了,大家可以在使用findbugs的過程中慢慢發現總結(#.#)

繼續閱讀