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.Map;
 import java.util.Set;
 
 import  org.apache.bcel.classfile.Code;
 import  org.apache.bcel.generic.Type;
 
 
 import  edu.umd.cs.findbugs.BugInstance;
 import  edu.umd.cs.findbugs.BugReporter;
 import  edu.umd.cs.findbugs.BytecodeScanningDetector;
 import  edu.umd.cs.findbugs.OpcodeStack;
 import  edu.umd.cs.findbugs.ba.ClassContext;
 
 public class PossibleConstantAllocationInLoop extends BytecodeScanningDetector {
 
     private static final Set<StringSYNTHETIC_ALLOCATION_CLASSES = new HashSet<String>();
     static {
         .add("java/lang/StringBuffer");
         .add("java/lang/StringBuilder");
         .add("java/lang/AssertionError");
     }
 
 	private final BugReporter bugReporter;
 	private OpcodeStack stack;
allocation number, info where allocated
 
reg, allocation number
 
 	private int nextAllocationNumber;
 
 	public PossibleConstantAllocationInLoop(BugReporter bugReporter) {
 		this. = bugReporter;
 	}
 
 	public void visitClassContext(ClassContext classContext) {
 		try {
 			 = new OpcodeStack();
 			super.visitClassContext(classContext);
 		} finally {
 			 = null;
 			 = null;
 			 = null;
 		}
 	}
 
 	public void visitCode(Code obj) {
 		.resetForMethodEntry(this);
 		super.visitCode(obj);
 
 		for (AllocationInfo info : .values()) {
 			if (info.loopBottom != -1) {
 				.reportBug(new BugInstance(this"PCAIL_POSSIBLE_CONSTANT_ALLOCATION_IN_LOOP", NORMAL_PRIORITY)
 							.addClass(this)
 							.addMethod(this)
 							.addSourceLine(getClassContext(), thisinfo.allocationPC));
 			}
 		}
 	}
 
 	public void sawOpcode(int seen) {
 		boolean sawAllocation = false;
 		Integer sawAllocationNumber = null;
 
 		try {
 			switch (seen)  {
 				case IFEQ:
 				case IFNE:
				case IFLT:
				case IFGE:
				case IFGT:
				case IFLE:
				case IF_ICMPEQ:
				case IF_ICMPNE:
				case IF_ICMPLT:
				case IF_ICMPGE:
				case IF_ICMPGT:
				case IF_ICMPLE:
				case IF_ACMPEQ:
				case IF_ACMPNE:
				case IFNULL:
				case IFNONNULL:
				case GOTO:
				case GOTO_W:
					if (getBranchOffset() < 0) {
						int branchLoc = getBranchTarget();
						int pc = getPC();
						for (AllocationInfo info : .values()) {
							if ((info.loopTop == -1) && (branchLoc < info.allocationPC)) {
								info.loopTop = branchLoc;
								info.loopBottom = pc;
							}
						}
					}
				break;
				case INVOKESPECIAL:
					if ("<init>".equals(getNameConstantOperand()) && "()V".equals(getSigConstantOperand())) {
							sawAllocationNumber = Integer.valueOf();
							.put(sawAllocationNumbernew AllocationInfo(getPC()));
							sawAllocation = true;
						}
					}
				//$FALL-THROUGH$
				case INVOKEINTERFACE:
				case INVOKEVIRTUAL:
				case INVOKESTATIC:
				    String signature = getSigConstantOperand();
					Type[] types = Type.getArgumentTypes(signature);
					if (.getStackDepth() >= types.length) {
						for (int i = 0; i < types.length; i++) {
							OpcodeStack.Item item = .getStackItem(i);
							Integer allocation = (Integer)item.getUserValue();
							if (allocation != null) {
								.remove(allocation);
							}
						}
		                if ((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL) || ((seen == INVOKESPECIAL))) {
		                    //ignore possible method chaining
		                    if (.getStackDepth() > types.length) {
    		                    OpcodeStack.Item item = .getStackItem(types.length);
    		                    Integer allocation = (Integer)item.getUserValue();
                                if (allocation != null) {
                                    String retType = Type.getReturnType(signature).getSignature();
                                    if (!"V".equals(retType) && retType.equals(item.getSignature())) {
                                        sawAllocationNumber = allocation;
                                        sawAllocation = true;
                                    }
                                }
		                    }
		                }
					}
				break;
				case ASTORE:
				case ASTORE_0:
				case ASTORE_1:
				case ASTORE_2:
				case ASTORE_3:
					if (.getStackDepth() > 0) {
						OpcodeStack.Item item = .getStackItem(0);
						Integer allocation = (Integer)item.getUserValue();
						if (allocation != null) {
							Integer reg = Integer.valueOf(RegisterUtils.getAStoreReg(thisseen));
							if (.values().contains(allocation)) {
								.remove(allocation);
else if (.containsKey(reg)) {
								.remove(allocation);
								allocation = .remove(reg);
								.remove(allocation);
else {
								.put(regallocation);
							}
						}
					}
				break;
				case AASTORE:
					if (.getStackDepth() >= 2) {
						OpcodeStack.Item item = .getStackItem(0);
						Integer allocation = (Integer)item.getUserValue();
						if (allocation != null) {
							.remove(allocation);
						}
					}
				break;
				case ALOAD:
				case ALOAD_0:
				case ALOAD_1:
				case ALOAD_2:
				case ALOAD_3: {
					Integer reg = Integer.valueOf(RegisterUtils.getALoadReg(thisseen));
					Integer allocation = .get(reg);
					if (allocation != null) {
						AllocationInfo info = .get(allocation);
						if ((info != null) && (info.loopBottom != -1)) {
							.remove(allocation);
else {
							sawAllocationNumber = allocation;
							sawAllocation = true;
						}
					}
				}
				break;
				case PUTFIELD:
					if (.getStackDepth() > 1) {
						OpcodeStack.Item item = .getStackItem(0);
						Integer allocation = (Integer)item.getUserValue();
						.remove(allocation);
					}
				break;
				case ARETURN:
				case ATHROW:
					if (.getStackDepth() > 0) {
						OpcodeStack.Item item = .getStackItem(0);
						Integer allocation = (Integer)item.getUserValue();
						if (allocation != null) {
							.remove(allocation);
						}
					}
				break;
			}
finally {
			TernaryPatcher.pre(seen);
			.sawOpcode(thisseen);
			TernaryPatcher.post(seen);
			if (sawAllocation) {
				if (.getStackDepth() > 0) {
					OpcodeStack.Item item = .getStackItem(0);
					item.setUserValue(sawAllocationNumber);
				}
				if (seen == INVOKESPECIAL)
			}
		}
	}
	static class AllocationInfo {
		int loopTop;
		public AllocationInfo(int pc) {
			 = -1;
			 = -1;
		}
	}
New to GrepCode? Check out our FAQ X