Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * fb-contrib - Auxiliary detectors for Java programs
   * Copyright (C) 2005-2013 Dave Brosius
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 package com.mebigfatguy.fbcontrib.detect;
 
 import java.util.List;
 
 import  org.apache.bcel.Repository;
 import  org.apache.bcel.classfile.Code;
 import  org.apache.bcel.classfile.CodeException;
 import  org.apache.bcel.classfile.ExceptionTable;
 import  org.apache.bcel.classfile.JavaClass;
 import  org.apache.bcel.classfile.Method;
 
 import  edu.umd.cs.findbugs.BugInstance;
 import  edu.umd.cs.findbugs.BugReporter;
 import  edu.umd.cs.findbugs.BytecodeScanningDetector;
 import  edu.umd.cs.findbugs.ba.ClassContext;

find methods that return or throw exception from a finally block. Doing so short-circuits the return or exception thrown from the try block, and masks it.
 
 public class AbnormalFinallyBlockReturn extends BytecodeScanningDetector {
 	private final BugReporter bugReporter;
     private int loadedReg;

    
constructs a AFBR detector given the reporter to report bugs on.

Parameters:
bugReporter the sync of bug reports
 
 	public AbnormalFinallyBlockReturn(final BugReporter bugReporter) {
 		this. = bugReporter;
 	}

overrides the visitor to check for java class version being as good or better than 1.4

Parameters:
classContext the context object that holds the JavaClass parsed
 
 	public void visitClassContext(ClassContext classContext) {
 		//TODO: Look at method calls in a finally block to see if they throw exceptions
 		//    : and those exceptions are not caught in the finally block
 		//    : Only do it if effort is on, ie: boolean fullAnalysis = AnalysisContext.currentAnalysisContext().getBoolProperty(FindBugsAnalysisFeatures.INTERPROCEDURAL_ANALYSIS_OF_REFERENCED_CLASSES);
 
 		try {
 	        int majorVersion = classContext.getJavaClass().getMajor();
 	        if (majorVersion >= MAJOR_1_4) {
 	        	 = new ArrayList<FinallyBlockInfo>();
 	        	super.visitClassContext(classContext);
 	        }
 		} finally {
         	 = null;
 		}
     }

overrides the visitor to collect finally block info.

Parameters:
obj the code object to scan for finally blocks
 
 	public void visitCode(Code obj) {
          = -1;
 
 		CodeException[] exc = obj.getExceptionTable();
 		if (exc != null) {
 			for (CodeException ce : exc) {
 				if ((ce.getCatchType() == 0)
 				&&  (ce.getStartPC() == ce.getHandlerPC())) {
                     .add(new FinallyBlockInfo(ce.getStartPC()));
 				}
 			}
         }
 
 		if (!.isEmpty())
 			super.visitCode(obj);
 	}

overrides the visitor to find return/exceptions from the finally block.

Parameters:
seen the opcode that is being visited
	public void sawOpcode(int seen) {
    	if (.isEmpty())
    		return;
		if (getPC() < fbi.startPC)
			return;
        if (getPC() == fbi.startPC) {
            if (seen == ASTORE)
                fbi.exReg = getRegisterOperand();
            else if ((seen >= ASTORE_0) && (seen <= ASTORE_3))
                fbi.exReg = seen - ASTORE_0;
            else {
                .remove(0);
                sawOpcode(seen);
                return;
            }
            return;
        }
		if (seen == MONITORENTER) {
			fbi.monitorCount++;
else if (seen == MONITOREXIT) {
			fbi.monitorCount--;
			if (fbi.monitorCount < 0) {
				sawOpcode(seen);
				return;
			}
		}
        if ((seen == ATHROW) && ( == fbi.exReg)) {
            .remove(0);
            sawOpcode(seen);
            return;
        }
        else if (seen == ALOAD)
             = getRegisterOperand();
        else if ((seen >= ALOAD_0) && (seen <= ALOAD_3))
             = seen - ALOAD_0;
        else
             = -1;
		if (((seen >= IRETURN) && (seen <= RETURN)) || (seen == ATHROW)) {
			.reportBug(new BugInstance( this"AFBR_ABNORMAL_FINALLY_BLOCK_RETURN", NORMAL_PRIORITY)
					.addClass(this)
					.addMethod(this)
					.addSourceLine(this));
else if ((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE) || (seen == INVOKESPECIAL) || (seen == INVOKESTATIC)) {
			try {
				JavaClass cls = Repository.lookupClass(getClassConstantOperand());
				if (m != null) {
					ExceptionTable et = m.getExceptionTable();
					if ((et != null) && (et.getLength() > 0)) {
						if (!catchBlockInFinally(fbi)) {
							.reportBug(new BugInstance( this"AFBR_ABNORMAL_FINALLY_BLOCK_RETURN", LOW_PRIORITY)
									.addClass(this)
									.addMethod(this)
									.addSourceLine(this));
						}
					}
				}
catch (ClassNotFoundException cnfe) {
				.reportMissingClass(cnfe);
			}
		}
	}

finds the method in specified class by name and signature

Parameters:
cls the class to look the method in
name the name of the method to look for
sig the signature of the method to look for
Returns:
the Method object for the specified information
	private Method findMethod(JavaClass clsString nameString sig) {
		Method[] methods = cls.getMethods();
		for (Method m : methods) {
			if (m.getName().equals(name) && m.getSignature().equals(sig)) {
				return m;
			}
		}
		return null;
	}

looks to see if any try/catch block exists inside this finally block, that wrap the current pc. This is a lax check as the try catch block may not catch exceptions that are thrown, but doing so would be prohibitively slow. But it should catch some problems.

Parameters:
fBlockInfo the finally block the pc is currently in
Returns:
if all exceptions are caught inside this finally block
	private boolean catchBlockInFinally(FinallyBlockInfo fBlockInfo) {
		CodeException[] catchExceptions = getCode().getExceptionTable();
		if ((catchExceptions == null) || (catchExceptions.length == 0))
			return false;
		int pc = getPC();
		for (CodeException ex : catchExceptions) {
			if ((ex.getStartPC() <= pc) && (ex.getEndPC() >= pc)) {
				if (ex.getStartPC() >= fBlockInfo.startPC) {
					return true;
				}
			}
		}
		return false;
	}

holds the finally block information for a particular method.
	public static class FinallyBlockInfo
	{
		public int startPC;
		public int monitorCount;
        public int exReg;

        
create a finally block info for a specific code range

Parameters:
start the start of the try block
		public FinallyBlockInfo(int start) {
			 = start;
             = -1;
		}
	}
New to GrepCode? Check out our FAQ X