`
knight_black_bob
  • 浏览: 853422 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Findbugs 使用备忘录

阅读更多

转自 : http://my.oschina.net/hoodlake/blog/126735

 

 

 

 

说明:
1.Bug
是findbug Eclipse插件原生的bug信息描述,Confidence 是fingbug团队认为该代码导致bug的可能性。
2.以下都是我使用findbug在公司项目中找到的一些bug,这里做一些中文的简短说明(不是翻译)
3.篇幅可能会有点长,阅读时,大家可以通过ctrl+f根据关键字查找自己相关的bug
BUG-0001
Bug
: Field only ever set to null: com.bettersoft.admin.BtCorpManager.ps 

All writes to this field are of the constant value null, and thus all reads of the field will return null. Check for errors, or remove it if it is useless.
Confidence
: Normal, Rank: Troubling (12)
Pattern
: UWF_NULL_FIELD 
Type: UwF, Category: CORRECTNESS (Correctness)
代码片段:

public class BtCorpManager {
	private BtCorp btcorp=null;
	private Connection con = null;
	private Statement st = null;
	private PreparedStatement ps = null;
	private ResultSet rs = null;
	private void setConnection(String centerno) throws Exception{
		//con = DBManager.getConnection(centerno);
		con = DBManager.getConnection();
	}

 

 

解释说明:在BtCorpManager类里面定了一个私有的成员变量PreparedStatement ps,但是这个成员变量ps在实例范围内没有得到任何的初始化(采用默认的构造方法),始终为null,所以在实例范围内使用该成员变量时,如果不先对其进行初始化操作或者无意识的行为忘了初始化操作,那肯定是要报空指针异常,所以这无疑是一个bug 

推荐修改: 自己看着办

 

BUG-0002
Bug: Nullcheck of form at line 36 of value previously dereferenced in com.bettersoft.admin.CorpEditAction.execute(ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse)

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.

Confidence: High, Rank: Scary (9)
Pattern: RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE 
Type: RCN, Category: CORRECTNESS (Correctness)
代码片段:

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
		//throw new UnsupportedOperationException("Method is not implemented");
		ActionErrors errors = new ActionErrors();
		CreateCorpActionForm createCorp = new CreateCorpActionForm();
		createCorp = (CreateCorpActionForm)form;
		
		
		CreateCorpActionForm webcorp=new CreateCorpActionForm();
		BudgetWebcorpManager budgetWebcorpManager=new BudgetWebcorpManager();
		webcorp=budgetWebcorpManager.getCWebcorp(createCorp.getId());
		createCorp.setFbsaddapproveid(webcorp.getFbsaddapproveid());
		createCorp.setFbsinputapproveid(webcorp.getFbsinputapproveid());
		createCorp.setFbsprocessapproveid(webcorp.getFbsprocessapproveid());

		boolean b=false;
		if(createCorp!=null){

 

 

解释说明:注意到有个局部变量 CreateCorpActionForm createCorp;再看下它的初始化过程,先是通过new给它分配了内存空间,紧接着有让它引用了了另一个未知的变量,这里说未知是指这个新的引用可能为空,显然 createCorp有可能指向一个空的地址,所以在接下来的引用中极可能报空指针异常(在引用之前不进行判空操作的话)! 在接下来的代码,如下

if(createCorp!=null){

其实也就没有存在的必要,因为如果为空的话,上面这行代码根本不可能执行到,所以findbug说这是冗余的空指针检查。当然考虑到特殊情况,这里显然是struts1的action,所以只要web应用正常启动,通常以下代码

 

createCorp = (CreateCorpActionForm)form;

 

 

是不会导致createCorp指向空的,唯一的缺陷就是之前的new操作是多余的。
推荐修改:自己看着办

BUG-0003
Bug: con is null guaranteed to be dereferenced in com.bettersoft.admin.leftAction.getLeft(int, String, String) 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).
Confidence
: Normal, Rank: (Troubling 11)
Pattern: NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH 
Type: NP, Category: CORRECTNESS (Correctness)
代码片段:

finally
		{
			try
			{
                if(rs != null)
				    rs.close();
				if(ps!=null)
                    ps.close();
				con.close();
			}catch(Exception ee)
			{
				ee.printStackTrace();
			}
		}

 

 

解释说明:这应该是大家很熟悉的代码片段了,可以想象Connection con是在catch代码块中进行的初始化操作,findbug对该bug说的很明白,说如果出现异常,Connection con将保证为空,因为很显然如果出现异常,con将得不到正确的初始化,即便初始化了,因为异常的出现,引用也会被解除,回到一开始定义处的null状态,那么在这里的finally代码块中调用Connection con的close()方法,将报空指针异常 

推荐修改:自己看着办 

BUG-0004 
Bug: Possible null pointer dereference of dbVersion in com.bettersoft.admin.LoginAction.loadVersion(HttpServletRequest, ActionErrors) on exception path 

A reference value which is null on some exception control path is dereferenced here. This may lead to aNullPointerExceptionwhen 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.

Confidence: Normal, Rank: Troubling (11)
Pattern: NP_NULL_ON_SOME_PATH_EXCEPTION 
Type: NP, Category: CORRECTNESS (Correctness)
代码片段:

VersionInfo dbVersion = null;
	try {
		con = DBManager.getConnection();
		dbVersion = vm.getVersionInfo(con);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} finally {
		try {
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
if (dbVersion.equals(programVersion)) {
	programVersion.setCorrent(true);
} else {
    programVersion.setCorrent(false);
}

 

 

解释说明:如果try catch 中捕获异常,那么dbVersion将为空, 

dbVersion.equals(programVersion)

上面这行代码,将报空指针异常 

 

BUG-0005
Bug
: Dead store to am in com.bettersoft.approve.action.CheckAction.execute(ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse)

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.

Confidence: High, Rank: Of Concern (15)
Pattern: DLS_DEAD_LOCAL_STORE 
Type: DLS, Category: STYLE (Dodgy code)
代码片段:

 ApproveManager am = new ApproveManager();

 

 

解释说明:am这个局部变量创建出来后,没有在任何地方被引用。这里确实没有被引用,所以是个bug,但是findbug又说明了,这有可能是误报,因为javac编译器在编译局部常量时,也会产生dead stroes。所以这个要视情况而定,不能过于纠结 



BUG-0006
Bug: The class name com.bettersoft.approve.form.BtWebCorp shadows the simple name of the superclass com.bettersoft.admin.BtWebCorp

This class has a simple name that is identical to that of its superclass, except that its superclass is in a different package (e.g.,alpha.Fooextendsbeta.Foo). This can be exceptionally confusing, create lots of situations in which you have to look at import statements to resolve references and creates many opportunities to accidently define methods that do not override methods in their superclasses.

Confidence: High, Rank: Troubling (14)
Pattern: NM_SAME_SIMPLE_NAME_AS_SUPERCLASS 
Type: Nm, Category: BAD_PRACTICE (Bad practice)

代码片段: 

 

public class BtWebCorp extends com.bettersoft.admin.BtWebCorp{

}

 

 

解释说明:这里子类和父类名称一样,findbug认为这回导致很多混淆。显然一旦出问题,将很难发现,运行结果将出乎意料 

BUG-0007
Bug: Comparison of String objects using == or != in com.byttersoft.admin.persistence.dao.MessageOpenDao.addOpenSave(MessageOpenForm)

This code comparesjava.lang.Stringobjects for reference equality using the == or != operators. Unless both strings are either constants in a source file, or have been interned using theString.intern()method, the same string value may be represented by two different String objects. Consider using theequals(Object)method instead.

Confidence: Normal, Rank: Troubling (11)
Pattern: ES_COMPARING_STRINGS_WITH_EQ 
Type: ES, Category: BAD_PRACTICE (Bad practice)

代码片段:

 

if(id==null || id==""){
    	sql = "insert into xx values (1,?,?,?)";
}else{
    	sql = "insert into xx values ((select max(id) + 1 from xx),?,?,?)";
}

 

解释说明: 直接使用==进行对象实例比较,而没有使用equals,本来没觉得这个bug咋样,但是发现项目里居然最多的bug就是这个,不管是很多年前的代码还是最近的代码,都存在这大量这样的问题。看来这是一个通病,所以大家注意一下,不光是我们公司的项目有这样的问题,这应该是一个普遍的问题,尤其实在比较String类型的时候,注意只要不是java基本类型都需要使用equals进行比较,哪怕是自动解封的Integer,Double等

 

BUG-0008
Bug: Call to String.equals(Double) in com.byttersoft.amm.util.BalanceInterzoneRateUtil.formatRate(Double)

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.

Confidence: High, Rank: Scariest (1)
Pattern: EC_UNRELATED_TYPES 
Type: EC, Category: CORRECTNESS (Correctness)
代码片段:

private static String  formatRate(Double r){
		
		if(r==null ||  ("undefined").equals(r)){
			return null;
		}

 

 

解释说明:使用equals比较不同类型的数据,"undefined"是String类型,r是Double类型,这两个比较肯定返回false

 

("undefined").equals(r)

 

 

上面这行代码完全没有必要 ,不可能存在这种情况

 

BUG-0009
Bug: Class com.byttersoft.util.CertInfo defines non-transient non-serializable instance field subjectDnAttr

This Serializable class defines a non-primitive instance field which is neither transient, Serializable, orjava.lang.Object, and does not appear to implement theExternalizableinterface or thereadObject()andwriteObject()methods. Objects of this class will not be deserialized correctly if a non-Serializable object is stored in this field.

Confidence: High, Rank: Troubling (14)
Pattern: SE_BAD_FIELD 
Type: Se, Category: BAD_PRACTICE (Bad practice)

代码片段: 

 

public class CertInfo implements java.io.Serializable
{
	private String subjectDN="";
	private String issuerDN="";
	private String notAfterDate="";
	private String notBeforeDate="";
	private String serialNumber="";
	private String sigAlgName="";
	private String sigAlgOID="";
	private String version="";
	private String publicKeyFormat="";
	private String publicKeyAlgorithm="";
	private Names subjectDnAttr=null;
}
public class Names
{}

 

解释说明: CertInfo实现的序列话,但是他的成员变量Names subjectDnAttr没有实现序列化,这将会导致序列化失败,String已经默认实现了序列化。注意,序列化时所有的成员变量都必须递归的实现序列化,否则将导致序列化失败。如果某个成员变量不想被序列化要么标注为瞬态要么重写readObj方法

 

BUG-0010
Bug: Dead store to corpGourps rather than field with same name in com.byttersoft.admin.form.CorpGroupsForm.setCorpGourps(CorpGourps)

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. There is a field with the same name as the local variable. Did you mean to assign to that variable instead?

Confidence: High, Rank: Scary (9)
Pattern: DLS_DEAD_LOCAL_STORE_SHADOWS_FIELD 
Type: DLS, Category: STYLE (Dodgy code)

代码片段:

 

 
public void setCorpGourps(CorpGourps corpGourps) {
		corpGourps = corpGourps;
	}

 

 

 

解释说明:成员变量和局部变量重名

 

BUG-0011
Bug
: Invocation of toString on labelValue in com.byttersoft.approve.persistence.dao.MesAppDao.getMapByPara(String)

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.

Confidence: Normal, Rank: Troubling (10)
Pattern: DMI_INVOKING_TOSTRING_ON_ARRAY 
Type: USELESS_STRING, Category: CORRECTNESS (Correctness)
代码片段:

for (String parameter : parameters) {
			String[] labelValue = parameter.split("=");
			if (labelValue.length == 2) {
				String key = labelValue[0];
				String value = labelValue[1];
				hashMap.put(key, value);
			} else {
				logger.debug("参数 " + labelValue + " 配置错误。");
			}
		}

 

 

解释说明:在进行日志输出时,直接输出对象,将默认调用对象的toString方法,而默认是输出对象的内存地址,所以这里显然有问题,本意应该是输出数组中的字符串 

 

BUG-0012
Bug
: Write to static field com.byttersoft.admin.service.BtSysResService.map from instance method com.byttersoft.admin.service.BtSysResService.hashCatchOfSysRes(boolean)

This instance method writes to a static field. This is tricky to get correct if multiple instances are being manipulated, and generally bad practice.

Confidence: High, Rank: Of Concern (15)
Pattern: ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD 
Type: ST, Category: STYLE (Dodgy code)

代码片段: 

 

static Map<String, BtSysRes> map = new HashMap<String, BtSysRes>();
public Map<String, BtSysRes> hashCatchOfSysRes(boolean isRefresh) {
		if(isRefresh == true){
			map = hashCatchOfSysRes();
		}else{
			if(map == null || map.isEmpty()){
				map = hashCatchOfSysRes();
			}
		}
		return map;
	}

 

 

解释说明:在实例方法中修改类变量的引用,这会导致共享问题,因为其他实例也会访问该静态变量,但是却不知道某个实例已经修改了该静态变量的引用,导致不可预知的问题
推荐修改:将该方法改为类方法



BUG-0013
Bug: Unwritten field: com.byttersoft.admin.service.importservice.ImportServices.bank

This field is never written. All reads of it will return the default value. Check for errors (should it have been initialized?), or remove it if it is useless.

Confidence: Normal, Rank: Troubling (12)
Pattern: UWF_UNWRITTEN_FIELD 
Type: UwF, Category: CORRECTNESS (Correctness)
代码片段:

public class ImportServices {
private IBankAccServices bank;
public IBankAccServices getBank() {
		return bank;
	}
}

 

 

解释说明: bank对象为空,getBank方法返回了一个肯定为空的对象实例

 

 

BUG-0014
Bug
: There is an apparent infinite recursive loop in com.byttersoft.amm.dao.impl.CheckLoanOrProvideInfoDaoImpl.addBatch(List)

This method unconditionally invokes itself. This would seem to indicate an infinite recursive loop that will result in a stack overflow.

Confidence: High, Rank: Scary (9)
Pattern: IL_INFINITE_RECURSIVE_LOOP 
Type: IL, Category: CORRECTNESS (Correctness)

代码片段: 

 

public void addBatch(List<CmsPLoanToBean> cmsPLoanBeans) {
        this.addBatch(cmsPLoanBeans);
    }

 

 

解释说明:出现了递归调用addBatch,将出现死循环

 

 

 

 

 

 

 

 

 

 

 

 

捐助开发者

在兴趣的驱动下,写一个免费的东西,有欣喜,也还有汗水,希望你喜欢我的作品,同时也能支持一下。 当然,有钱捧个钱场(右上角的爱心标志,支持支付宝和PayPal捐助),没钱捧个人场,谢谢各位。



 
 
 谢谢您的赞助,我会做的更好!

 

 

 

分享到:
评论

相关推荐

    findbugs使用说明

    FindBugs 使用说明 FindBugs 是一个静态分析工具,用于检查 Java 字节码,查找可能存在的 bug 和代码缺陷。它可以检查未关闭的数据库连接、缺少必要的 null 检查、多余的 null 检查、多余的 if 后置条件、相同的...

    findbugs安装及使用手册

    3. **FindBugs使用** - **Eclipse集成**:在Eclipse中,右键点击项目,选择"FindBugs" &gt; "Check for Bugs",分析完成后,结果会显示在"FindBugs"视图中。双击问题可以跳转到相应的代码行。 - **Maven执行**:在...

    FindBugs安装与使用说明

    《FindBugs安装与使用详解》 FindBugs是一款开源的静态代码分析工具,主要用于Java程序的错误检测。它能够帮助开发者在代码运行前找出潜在的bug,提高代码质量和可维护性。本篇文章将详细介绍FindBugs的安装过程...

    Findbugs使用教程

    FindBugs是一个专门分析JAVA代码问题的静态代码扫描工具,在FindBugs中,选择待扫描的文件(FindBugs其实就是对编译后的class进行扫描,藉以发现一些隐藏的bug。)。如果这些.class文件有对应的源文件,这样便可以从...

    eclipse中FindBugs_安装使用

    ### Eclipse中FindBugs的安装与使用详解 #### 一、FindBugs简介 FindBugs是一款用于检测Java代码潜在缺陷的强大工具。它能够帮助开发者及时发现并修复代码中的问题,提高软件的质量和稳定性。FindBugs支持多种版本...

    Findbugs使用简介

    《Findbugs使用简介》 Findbugs是一款开源的静态代码分析工具,主要针对Java代码进行分析,旨在检测出可能存在的错误和潜在的问题。它通过分析字节码而非源代码,能够发现那些编译器无法捕捉的运行时错误和设计缺陷...

    findbugs插件使用文档

    在Maven项目中,我们可以使用`findbugs-maven-plugin`这个Maven插件来集成FindBugs。 配置`findbugs-maven-plugin`的步骤如下: 1. 在Maven项目的`pom.xml`文件中,找到`&lt;reporting&gt;`标签,然后添加以下配置: ```...

    findbugs 1.3.9 findbugs 1.3.9

    3. **可扩展性**:FindBugs支持插件机制,用户可以自定义规则或使用社区提供的扩展,以适应特定的项目需求。 4. **集成友好**:1.3.9版本提供了对Eclipse的集成,通过edu.umd.cs.findbugs.plugin.eclipse_1.3.9....

    FindBugs完全使用手册

    ### FindBugs完全使用手册 #### 一、FindBugs简介与重要性 FindBugs是一款专门用于Java字节码静态分析的工具,其主要功能在于帮助开发人员提高代码质量并发现潜在的缺陷。该工具通过对类文件或JAR文件进行分析,并...

    findbugs压缩包+findbugs.jar+findbugs-ant.jar

    综上所述,这个压缩包提供了FindBugs的完整环境,包括核心库、Ant任务支持以及Eclipse插件,涵盖了FindBugs的安装、配置、使用和结果分析等多个方面。使用FindBugs,开发者能够尽早发现潜在的bug,避免它们在实际...

    网络上搜集的Findbugs在Ant下的配置方法

    **Findbugs在Ant下的配置方法** FindBugs是一款开源的静态代码分析工具,主要用于检测Java代码中的潜在错误、坏味道和安全漏洞。...正确配置和使用FindBugs,能帮助你尽早发现并修复潜在的错误,减少后期维护的成本。

    FindBugs安装及配置使用说明

    FindBugs是一款强大的Java字节码静态分析工具,它能够帮助开发者在代码执行前发现潜在的缺陷和质量问题。...熟练掌握FindBugs的安装、配置和使用,对于提升Java开发者的代码审查能力和项目质量具有显著作用。

    最新版checkstyle,findbugs以及安装使用说明

    最新版checkstyle,findbugs以及安装使用说明。测试无误,可以使用

    findbugs.jar+findbugs-ant.jar

    "findbugs"标签表示这个话题与FindBugs工具相关,而"eclipse"标签则意味着讨论的是在Eclipse环境下使用FindBugs。通过这两个标签,我们可以理解这是一个关于在Eclipse集成环境中使用FindBugs进行静态代码分析,并...

    findbugs使用实例

    自己整理的findbugs的简单使用实例

Global site tag (gtag.js) - Google Analytics