findbugs 问题说明。

findbugs 出错类型及对应解释 第一弹


1、Dead store to local variable 本地变量存储了闲置不用的对象
举例:
List accountCoList = new ArrayList();
我们为accountCoList新建了一个对象,但是程序的后面并没有使用这个这个新建对象。
建议改为:
List accountCoList = null;

2、Write to static field from instance method 向static字段中写入值
举例:
 private static DBRBO dbrBO;
 public final void refresh() {
        danskeBankBO = null;
        dbrBO = null;
        fileAndPathBO = null;
    }
建议改为:
去掉static。


3、Load of known null value 大体意思是加载了null的对象。
举例
        if (null == boList) {

            for (int i = 0; i < boList.size(); i++) {
                entityList.add(productBOToEntity(boList.get(i)));
            }
        }


4、Exception is caught when Exception is not thrown 这个意思比较好理解:就是catch了异常但是try里并没有抛出异常


5、Method ignores exceptional return value 没有对方法的异常返回值进行检查


6、Comparison of String objects using == or !=
  This code compares java.lang.String objects for reference equality using the == or != operators.
  Unless both strings are either constants in a source file, or have been interned using the String.intern() method,
  the same string value may be represented by two different String objects. Consider using the equals(Object) method
  instead.
  从字面意思可以理解String对象进行比较的时候:只有两种情况可以使用== or !=的,这两种情况是;在源文件中是个常数或者是调用
  String.intern()方法,使用String的规范化表示形式来进行比较,如果不是这两中情况的话推荐使用.equals(object)方式

7、Method names should start with a lower case letter 这个好理解方法名的第一个字母不能是大写

8、Non-transient non-serializable instance field in serializable class
  This Serializable class defines a non-primitive instance field which is neither transient, Serializable,
  or java.lang.Object, and does not appear to implement the Externalizable interface or the readObject()
  and writeObject() methods.? Objects of this class will not be deserialized correctly if a non-Serializable object
  is stored in this field.


  这个错误的意思是:在可序列化的类中存在不能序列化或者不能暂存的数据


findbugs 出错类型及对应解释 第二弹

1、Bug: Hard coded reference to an absolute pathname

   BUG描述:This code constructs a File object using a hard coded to an absolute pathname(此代码包含文件对象为一个绝对路径名)
 
   问题原因:硬编码指向绝对路径。
 
  File preFile = new File(PREFERENCES_FILE_FULL_PATH);
 
 而private static final String PREFERENCES_FILE_FULL_PATH =
 
        "/data/data/com.android.mms/shared_prefs/auto_downLoad.xml";
 
PREFERENCES_FILE_FULL_PATH声明为了final型,不可变的。如果后续文件路径有变更,引用不到了,但路径又不可更改,就会引入问题。
 
解决方法:去掉final。
 
2、Bug: Pattern: Dead store to local variable
 
BUG描述: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. (该指令为局部变量赋值,但在其后的没有对她做任何使用。通常,这表明一个错误,因为值从未使用过。)
 
问题原因:锁屏中提示Dead store to velocityX,分析代码
 
case MotionEvent.ACTION_POINTER_1_UP
语句中定义了局部变量velocityX,
并且只在if ((mDirectionFlag && velocityX > 0)||(!mDirectionFlag && velocityX < 0))
velocityX = -velocityX;中赋值后并未再使用。因此没有赋值的必要,并且分析代码不需要该变量,可以去除。
 
解决方法:去掉velocityX变量的定义及赋值。
 
3、BUG: Inconsistent synchronization
BUG描述:The fields of this class appear to be accessed inconsistently with respect to synchronization. (不合理的同步)
 
问题原因:根据描述ConfigLoader文件中mUnlockAppDataMap在46%的时间内都是处于被锁状态。
分析代码mUnlockAppDataMap是在checkUnlockAppConfigChange这个函数中被锁的。
而该方法public synchronized boolean checkUnlockAppConfigChange(Context context)没有地方调用。
 
解决方法:去掉synchronized关键字。
 
4、BUG: Incorrect lazy initialization of static field
 
BUG描述:This method contains an unsynchronized lazy initialization of a non-volatile static field.
Because the compiler or processor may reorder instructions, threads are not guaranteed to see a completely
initialized object, if the method can be called by multiple threads.(这种方法包含了一个不同步延迟初始化的
非volatile静态字段。因为编译器或处理器可能会重新排列指令,如果该方法可以被多个线程调用,线程不能保证看到一个完全初始化的对象。)
 
问题原因:sInstance 是static型,clean()方法可能被多个线程调用,在sInstance判断为非空后,再清空置null时可能会有问题。
 
解决方法:给clean()加上关键字synchronized .public static synchronized void clean()
 
5、BUG: Redundant nullcheck of value known to be non-null
 
BUG描述:This method contains a redundant check of a known non-null value against the constant null.(方法中对不为空的值进行为空的判断。)
 
问题原因:分析findbugs报错的这段代码
 
if(mInputStream == null){
 
Log.i(TAG , " mInputStream is null ");
 
return;
 
}
 
mDBuilder = mDBuilderFactory.newDocumentBuilder();
 
if(mInputStream != null) {
 
mDocument = mDBuilder.parse(mInputStream);
 
}else {
 
Log.i(TAG , "mInputStream ==  null");
 
return;
 
}
 
mInputStream若为null,则直接返回。后面不需要再有if(mInputStream != null)的判断。
 
解决方法:在mInputStream判空后不再重复判空,将后面if判断中的mInputStream改为mDBuilder。
 
6、BUG: Should be a static inner class
 
BUG描述:This class is an inner class, but does not use its embedded reference to the object which created it. 
This reference makes the instances of the class larger, and may keep the reference to the creator object alive longer than necessary. 
If possible, the class should be made static.(若成员类中未访问外围类的非静态成员,为避免额外的空间和时间开销,建议改用静态成员类。)
 
问题原因:非静态成员类和静态成员类的区别在于,非静态成员类是对象的,静态成员类是类的。非静态成员类可以访问外围类的任何成员,
但前提是必须存在外围类对象。JAVA需要额外维护非静态成员类和外围类对象的关系。分析代码private class IccText和private class
MediaMetadata {没有访问到外围类的非静态成员,所以findbugs建议将其设为static型。
 
解决方法:将这2个内部类改为static型。
 
7、BUG: Switch statement found where one case falls through to the next case
BUG描述:This method contains a switch statement where one case branch will fall through to the next case.
Usually you need to end this case with a break or return.(Switch语句中一个分支执行后又执行了下一个分支。
通常case后面要跟break或者return语句来跳出。)
 
问题原因:case MotionEvent.ACTION_UP执行完之后没有break,会继续走case MotionEvent.ACTION_CANCEL分支。
分析代码逻辑,手指抬起后,锁屏图标需要回到初始位置,而回到初始位置的逻辑是在ACTION_CANCEL里做的。
即ACTION_UP后的逻辑还需要ACTION_CANCEL里面的逻辑。
 
解决方法:将ACTION_CANCEL中的逻辑拉出来做成一个函数,ACTION_UP逻辑后调用这个函数后再做break操作。
 
8、BUG: Unread field
BUG描述:This field is never read.  Consider removing it from the class.(类中定义的属性从未被调用,建议删除。)
 
问题原因:在类中定义了成员变量private HwViewProperty mCondition = null;代码中只有赋值操作
mCondition = new HwViewProperty(mContext,value, ViewPropertyType.TYPE_CONDITION, mCallback);但没有使用这个变量mCondition的地方。
 
解决方法:去掉mCondition的定义及赋值语句。但需注意,mCondition = new HwViewProperty(mContext,value, ViewPropertyType.
TYPE_CONDITION, mCallback);赋值中,虽然mCondition变量后续没有使用到,但new HwViewProperty对象调用HwViewProperty的构造方法时,其实是做了功能操作的。
因此,去掉mCondition,但需要保留new HwViewProperty(mContext,value, ViewPropertyType.TYPE_CONDITION, mCallback);
 
9、BUG: Write to static field from instance method
BUG描述:This instance method writes to a static field. This is tricky to get correct if multiple instances are being manipulated, and generally bad practice.(实例方法直接写静态变量。)
 
问题原因:sInstance是类的静态成员变量,非静态方法unregisterCallbaks直接对其赋值,非静态方法是与对象相关联的,当多个对象同时对该变量进行赋值时可能出现问题。
 
解决方法:在使用静态成员变量时使用get和set方法。

findbugs 出错类型及对应解释 第三弹

最近使用findbugs分析了最近做过的一个project,发现自己写的代码出现好多问题,在这里做一个小小的总结。

下面是针对我的代码中出现的bug结合网络做了一下分析学习,借助Google翻译,感觉翻译的仍然很别扭。

 

May expose internal representation by incorporating reference to mutable   
object.This code stores a reference to an externally mutable   
object into the internal representation of the object.If instances  
are accessed by untrusted code,and unchecked changes to the mutable object would compromise security or

other important properties,you will need to do something different.  
Storing a copy of the object is better approach in many situations.
可能因使引用可指向多个对象而暴露内部存储结构。
这代码使一个指向外部多个对象的引用指向了一个内部对象存储地址。  
如果实例被未被信任代码访问或多个对象发生了未经检查的改变就会危及安全性或其它重要属性,
你需要去做一些不同的事情。存储一个对象的拷贝在许多情况下会是一个更好的方法。
网上findbug使用的介绍文章中写到,按下面修改findbug就没bug提示了,
为什么要放到一个临时变量中就可以了?

Java代码 
public class Test {  
  •   
  • String[] temp = name;  
  • }  
Java代码 
public void setName(String[] name) {  
  • String[] temp = name;  
  • }  
  • }  

 

因为代码中会经常出现getter/setter,我觉得这个bug是不必要进行修改的。

 

Dead store to local variable
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.
本地变量存储了闲置不用的对象,也就是说这个变量是多余的。
Hashtable   hTable = new  Hashtable();   
Object   obj = new   Object();  
obj =  hTable.put("uuid",   "abcd1234"); 

 

Java代码 
String abc = "abc";  
  • new String("");  
  • xyz = abc;  
  • System.out.println(xyz);  

 
用findbug檢查會出現Dead store to local variable的錯誤,他的意思是“本地变量存储了闲置不用的对象”
為什么會出現這個原因呢? 因為 String xyz = new String("");
  这一句执行3个动作:   
  1)创建一个引用xyz   
  2)创建一个String对象   
  3)把String的引用赋值给xyz
  其中,后面两个动作是多余的,因为后面的程序中你没有使用这个新建的String对象,而是重新给xyz赋值,  
xyz = abc;所以,只需要String xyz = abc; 就可以了。这样,findbugs就不会报了。

 

Write to static field from instance method
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字段中写入值,如:

Java代码 
private static Logger logger;  
  • public XXXActionCtrl(){  
  •   logger = Logger.getLogger(getClass());  
  •  }  
  • static Logger logger = Logger.getLogger(getClass());  

Unread field: should this field be static?
This class contains an instance final field that is initialized to a compile-time static value. Consider

making the field static.
未读的领域:这个领域应该是静态的?
这个类包含一个实例的最后字段初始化为编译时静态值。考虑静态的领域。(findbugs建议修改该属性为static的)。
如:private final String FAIL_FLAG = "exit";
改为:private static final String FAIL_FLAG = "exit";


Unread field 
This field is never read.  Consider removing it from the class. 
未读的领域(字段,属性)
类中声明了从未用过的字段。考虑从类中删除。

 

Method concatenates strings using + in a loop
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.
字符串串联使用方法在一个循环+
该方法似乎是建立在循环使用字符串串联。在每次迭代中,字符串转换为一个StringBuffer / StringBuilder的,附加到

,并转换回为String。这可能导致成本的二次迭代,因为不断增长的字符串是在每次迭代中重新复制。
更好的性能,可使用StringBuffer(或StringBuilder的)会更好一些。

Java代码 
For example:  
  • // This is bad  
  • "";  
  • for (int i = 0; i < field.length; ++i) {  
  •     s = s + field[i];  
  •   }  
  •   
  • // This is better  
  • new StringBuffer();  
  • for (int i = 0; i < field.length; ++i) {  
  •     buf.append(field[i]);  
  •   }  
  •   String s = buf.toString();  

  

Inefficient use of keySet iterator instead of entrySet 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迭代器而不是entrySet迭代器。
使用entrySet效率会比keySet高。
keySet()迭代后只能通过get()取key。
entrySet()迭代后可以e.getKey(),e.getValue()取key和value,返回的是Entry接口。

Field isn't final but should be.
A mutable static field could be changed by malicious code or by accident from another package. The field

could be made final to avoid this vulnerability.
字段应该声明为final,实际上却未声明final。
一个易变的static字段可以被恶意代码改变,使用final关键字以避免此漏洞。

 

Call to equals() with null argument.
This method calls equals(Object), passing a null value as the argument. According to the contract of the equals() method, this call should always return false.
使用null参数调用equals()。
此方法调用等于(对象),作为参数传递一个空值。根据合同的equals()方法,此调用应始终返回false。
如:queryStr.equals(null); 这样使用是不可取的,虽然能够通过编译。

 

Invocation of toString on an array.
The code invokes toString on an array, which will generate a fairly useless result such as [C@16f0472.

Consider using Arrays.toString to convert the array into a readable String that gives the contents of the array. See Programming Puzzlers, chapter 3, puzzle 12.
对数组调用toString()方法。
代码在对数组调用toString()方法时,将产生一个相当无用的形如 [C@16f0472 的结果。考虑使用 Arrays.toString方法

将数组转化为一个可读的给出数组内容的字符串。
比如:在使用System.out.println(xx.readNext());时候会碰到这样的提示,readNext() 方法放回一个String[]。
可改为:
String[] arr = reader.readNext();
System.out.println(Arrays.asList(arr).toString());
(好像有点麻烦,没想到更简洁的办法)。


Nullcheck of value previously dereferenced
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值检查。
一个值被选中这里看它是否是空的,但这个值不能为空,因为它在此之前废弃null值检查,而且如果它为null,空指针异

常将会发生在此处,如果它是空一空指针异常会发生在较早取消引用。
从本质上讲,此代码和前边废弃的null值检查将会出现不一致,是否这个值是容许
空。
出现该bug有两种情况:多余的null检查;前边废弃null值检查的。
比如:我们经常会这个使用ActionForm,
String clazzId = request.getParameter("clazzId");// script1
studentForm.setClazzID(clazzId);// script2
往往会在script2会出现该错误,因为在script1出未检查clazzId是否为null才导致的。
修改为 : 
if(clazzId != null) {
studentForm.setClazzID(clazzId);
}

在设置使用clazzId之前先判断其是否为null。

 

Possible null pointer dereference in method on exception path
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值检查,可能会导致后面的代码出现空指针异常。如:

Java代码 
md = null;  
  •    md = MessageDigest.getInstance("SHA-256");  
  •    md.update(bt);  
  • catch (NoSuchAlgorithmException e) {  
  • // script1  
  •   }  
  • byte[] digest = md.digest();// script2  
  • return;  

 

Possible null pointer dereference
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.
可能的空指针引用。
如在JDBC编程时候,在关闭ResultSet时候(rs.close()),经常会出现这个bug,解决办法很容易想到,判断是否为null或

使用try...catch...finally。

 

Call to equals() comparing different types
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.
调用equals()比较不同的类型。
此方法调用相当于两个不同的类类型的引用,没有共同的子类(对象)。
因此,所比较的对象是不太可能在运行时相同的类成员(除非一些
应用类没有分析或动态类加载可以发生在运行时)。据
equals()的规则,不同类的对象应始终比较不平等,因此,根据
由java.lang.Object.equals定义的合同(对象),FALSE将永远是比较的结果
在运行时错误。

。。。

posted @ 2016-07-29 14:59  andyLdn  Views(1281)  Comments(0Edit  收藏  举报