Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package com.mebigfatguy.fbcontrib.detect;
  
  import java.util.Arrays;
  import java.util.BitSet;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
 import java.util.Set;
 
 import  org.apache.bcel.Constants;
 import  org.apache.bcel.Repository;
 import  org.apache.bcel.classfile.Code;
 import  org.apache.bcel.classfile.CodeException;
 import  org.apache.bcel.classfile.ConstantClass;
 import  org.apache.bcel.classfile.ConstantPool;
 import  org.apache.bcel.classfile.JavaClass;
 import  org.apache.bcel.generic.Type;
 
looks for two or more try catch blocks that are consecutive and catch the same kind of exception, and throw the same exception always. These blocks can be coalesced into one.
 
 
 public class StackedTryBlocks extends BytecodeScanningDetector {
 
     private static JavaClass THROWABLE_CLASS;
 
     static {
         try {
              = Repository.lookupClass("java.lang.Throwable");
         } catch (ClassNotFoundException cnfe) {
              = null;
         }
     }
 	private final BugReporter bugReporter;
 	private List<TryBlockblocks;
 	private List<TryBlockinBlocks;
 	private OpcodeStack stack;
 
 	public StackedTryBlocks(BugReporter bugReporter) {
 		this. = bugReporter;
 	}
 
 	public void visitClassContext(ClassContext classContext) {
 		try {
 		    if ( != null) {
     			 = new OpcodeStack();
     			super.visitClassContext(classContext);
 		    }
 		} finally {
 			 = null;
 		}
 	}
 
 	public void visitCode(Code obj) {
 
 		try {
 			XMethod xMethod = getXMethod();
 			String[] tes = xMethod.getThrownExceptions();
 			Set<StringthrownExceptions = new HashSet<String>(Arrays.<StringasList((tes == null) ? new String[0] : tes));
 
 			 = new ArrayList<TryBlock>();
 			 = new ArrayList<TryBlock>();
 
 			CodeException[] ces = obj.getExceptionTable();
 			for (CodeException ce : ces) {
 				TryBlock tb = new TryBlock(ce);
 				int existingBlock = .indexOf(tb);
 				if (existingBlock >= 0) {
 					tb = .get(existingBlock);
 					tb.addCatchType(ce);
 				} else {
 					.add(tb);
 				}
 			}
 
 			while (it.hasNext()) {
 				TryBlock block = it.next();
 				if (block.hasMultipleHandlers() || block.isFinally()
 						|| block.catchIsThrown(getConstantPool(), thrownExceptions)) {
 					it.remove();
 				}
			}
			if (.size() > 1) {
				super.visitCode(obj);
				if (.size() > 1) {
                    Collections.sort();
                    TryBlock firstBlock = .get(0);
					for (int i = 1; i < .size(); i++) {
						TryBlock secondBlock = .get(i);
						if (!blocksSplitAcrossTransitions(firstBlocksecondBlock)) {
    						if ((firstBlock.getCatchType() == secondBlock.getCatchType())
                                    && (firstBlock.getThrowSignature().equals(secondBlock.getThrowSignature())
                                    && (firstBlock.getMessage().equals(secondBlock.getMessage())
    								&& (firstBlock.getExceptionSignature().equals(secondBlock.getExceptionSignature()))))) {
    							.reportBug(new BugInstance(this"STB_STACKED_TRY_BLOCKS", NORMAL_PRIORITY)
    									.addClass(this).addMethod(this)
    									.addSourceLineRange(thisfirstBlock.getStartPC(), firstBlock.getEndHandlerPC())
    									.addSourceLineRange(thissecondBlock.getStartPC(), secondBlock.getEndHandlerPC()));
    						}
						}
						firstBlock = secondBlock;
					}
				}
			}
finally {
			 = null;
			 = null;
		}
	}
	public void sawOpcode(int seen) {
	    String message = null;
		try {
	        .precomputation(this);
	        
		    if ((seen == TABLESWITCH) || (seen == LOOKUPSWITCH)) {
		        for (int offset : getSwitchOffsets()) {
		            .add(Integer.valueOf(offset));
		        }
		    } else if (isBranch(seen)) {
		        // throw out try blocks in loops, this could cause false negatives
		        // with two try/catches in one loop, but more unlikely
		        if (getBranchOffset() < 0) {
		            Iterator<TryBlockit = .iterator();
		            int target = getBranchTarget();
		            while (it.hasNext()) {
		                TryBlock block = it.next();
		                if (block.getStartPC() >= target) {
		                    it.remove();
		                }
		            }
		        }
		    }
			int pc = getPC();
			if (block != null) {
				.add(block);
			}
			if (.size() > 0) {
				TryBlock innerBlock = .get(.size() - 1);
				int nextPC = getNextPC();
				if (innerBlock.atHandlerPC(nextPC)) {
					if ((seen == GOTO) || (seen == GOTO_W)) {
else {
						.remove(innerBlock);
						.remove(innerBlock);
					}
else if (innerBlock.atHandlerPC(pc)) {
else if (innerBlock.atEndHandlerPC(pc)) {
				}
				if (innerBlock.inCatch()) {
					if (((seen >= Constants.IFEQ) && ((seen <= Constants.RET)))
							|| ((seen >= Constants.IRETURN) && (seen <= Constants.RETURN)) || (seen == GOTO_W)) {
						.remove(innerBlock);
else if (seen == ATHROW) {
						if (.getStackDepth() > 0) {
							XMethod xm = item.getReturnValueOf();
							if (xm != null) {
							    innerBlock.setThrowSignature(xm.getSignature());
							}
                            innerBlock.setExceptionSignature(item.getSignature());
                            innerBlock.setMessage((Stringitem.getUserValue());
else {
						}
else if ((seen == INVOKESPECIAL) && "<init>".equals(getNameConstantOperand())) {
					    String cls = getClassConstantOperand();
					    JavaClass exCls = Repository.lookupClass(cls);
					    if (exCls.instanceOf()) {
					        String signature = getSigConstantOperand();
					        Type[] types = Type.getArgumentTypes(signature);
					        if (types.length > 0) {
					            if ("Ljava/lang/String;".equals(types[0].getSignature())) {
    					            if (.getStackDepth() >= types.length) {
    					                OpcodeStack.Item item = .getStackItem(types.length - 1);
    					                message = (String)item.getConstant();
    					                if (message == null) {
    					                    message = "____UNKNOWN____" + System.identityHashCode(item);
    					                }
    					            }
					            }
					        } else {
					            message = "";
					        }
					    }
					}
				}
			}
catch (ClassNotFoundException cnfe) {
finally {
			.sawOpcode(thisseen);
			if ((message != null) && (.getStackDepth() > 0)) {
			    OpcodeStack.Item item = .getStackItem(0);
			    item.setUserValue(message);
			}
		}
	}
	private TryBlock findBlockWithStart(int pc) {
		for (TryBlock block : ) {
			if (block.atStartPC(pc)) {
				return block;
			}
		}
		return null;
	}
	private boolean blocksSplitAcrossTransitions(TryBlock firstBlockTryBlock secondBlock) {
	    if (!.isEmpty()) {
    	    Iterator<Integerit = .iterator();
    	    while (it.hasNext()) {
    	        Integer transitionPoint = it.next();
    	        if (transitionPoint.intValue() < firstBlock.handlerPC) {
    	            it.remove();
    	        } else {
    	            return transitionPoint.intValue() < secondBlock.handlerPC;
    	        }
    	    }
	    }
	    return false;
	}
	static class TryBlock {
		public enum State {
			BEFORE, IN_TRY, IN_CATCH, AFTER
		};
		int startPC;
		int endPC;
		public TryBlock(CodeException ce) {
			 = ce.getStartPC();
			 = ce.getEndPC();
			 = ce.getHandlerPC();
			 = new BitSet();
			.set(ce.getCatchType());
		}
		public void addCatchType(CodeException ce) {
			.set(ce.getCatchType());
		}
		public void setState(State executionState) {
			 = executionState;
		}
		public boolean inCatch() {
			return  == .;
		}
		public boolean hasMultipleHandlers() {
			int bit = .nextSetBit(0);
			return .nextSetBit(bit + 1) >= 0;
		}
		public boolean isFinally() {
			return .get(0);
		}
		public boolean catchIsThrown(ConstantPool poolSet<StringthrownExceptions) {
			if (thrownExceptions.size() > 0) {
				int exIndex = .nextSetBit(0);
				String exName = ((ConstantClass) pool.getConstant(exIndex)).getBytes(pool);
				return thrownExceptions.contains(exName);
			}
			return false;
		}
		public void setEndHandlerPC(int end) {
			 = end;
		}
		public void setExceptionSignature(String sig) {
		     = sig;
		}
		public void setThrowSignature(String sig) {
			 = sig;
		}
		public void setMessage(String m) {
		     = m;
		}
		    return ( == null) ? String.valueOf(System.identityHashCode(this)) : ;
		}
			return ( == null) ? String.valueOf(System.identityHashCode(this)) : ;
		}
		public String getMessage() {
            return ( == null) ? String.valueOf(System.identityHashCode(this)) : ;
		}
		public int getStartPC() {
			return ;
		}
		public int getEndHandlerPC() {
			return ;
		}
		public boolean atStartPC(int pc) {
			return  == pc;
		}
		public boolean atHandlerPC(int pc) {
			return  == pc;
		}
		public boolean atEndHandlerPC(int pc) {
			return ( >= 0) && ( == pc);
		}
		public int getCatchType() {
		}
		public int hashCode() {
			return  ^ ;
		}
		public boolean equals(Object o) {
			if (o instanceof TryBlock) {
				TryBlock that = (TryBlocko;
				return ( == that.startPC) && ( == that.endPC);
			}
			return false;
		}
		public String toString() {
			return "{" +  + " -> " +  + "} (catch " + .nextSetBit(0) + ") {" +  + " -> "
 + "}";
		}
	}
New to GrepCode? Check out our FAQ X