Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * fb-contrib - Auxiliary detectors for Java programs
   * Copyright (C) 2005-2015 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 java.util.Map;
 import java.util.Set;
 
 
 
looks for deletion of items from a collection using the remove method of the collection at the same time that the collection is being iterated on. If this occurs the iterator will become invalid and throw a ConcurrentModificationException. Instead, the remove should be called on the iterator itself.
 
 {
 	private static JavaClass collectionClass;
 	private static JavaClass iteratorClass;
 	private static Set<JavaClassexceptionClasses;
 	private static final Set<StringcollectionMethods;
 	static {
 		try {
 			 = Repository.lookupClass("java/util/Collection");
 			 = Repository.lookupClass("java/util/Iterator");
 		} catch (ClassNotFoundException cnfe) {
 			 = null;
 			 = null;
 		}
 
 		try {
 			.add(Repository.lookupClass("java/util/concurrent/CopyOnWriteArrayList"));
 			.add(Repository.lookupClass("java/util/concurrent/CopyOnWriteArraySet"));
 		} catch (ClassNotFoundException cnfe) {
 			//don't have a bugReporter yet, so do nothing
 		}
 
 		.add("entrySet()Ljava/lang/Set;");
 		.add("keySet()Ljava/lang/Set;");
 		.add("values()Ljava/lang/Collection;");
 	}
 	private static final Map<StringIntegermodifyingMethods = new HashMap<StringInteger>(8);
 	static {
 		.put("add(Ljava/lang/Object;)Z".);
 		.put("addAll(Ljava/util/Collection;)Z".);
 		.put("addAll(ILjava/util/Collection;)Z".);
 		.put("clear()V".);
 		.put("remove(I)Ljava/lang/Object;".);
 		.put("removeAll(Ljava/util/Collection;)Z".);
 		.put("retainAll(Ljava/util/Collection;)Z".);
	}
	private final BugReporter bugReporter;
	private OpcodeStack stack;
	private Map<IntegerLooploops;
constructs a DWI detector given the reporter to report bugs on

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

implements the visitor to setup the opcode stack, collectionGroups, groupToIterator and loops

Parameters:
classContext the context object of the currently parsed class
	public void visitClassContext(ClassContext classContext) {
		if (( == null) || ( == null))
			return;
		try {
			 = new OpcodeStack();
			 = new HashMap<IntegerLoop>(10);
			super.visitClassContext(classContext);
finally {
			 = null;
			 = null;
			 = null;
		}
	}

implements the visitor to reset the stack, collectionGroups, groupToIterator and loops

Parameters:
obj the context object of the currently parsed code block
	public void visitCode(Code obj) {
		super.visitCode(obj);
	}

implements the visitor to look for deletes on collections that are being iterated

Parameters:
seen the opcode of the currently parsed instruction
	public void sawOpcode(int seen) {
		int groupId = -1;
		try {
	        .precomputation(this);
	        
			if (seen == ) {
				String methodName = getNameConstantOperand();
				String signature = getSigConstantOperand();
				String methodInfo = methodName + signature;
				if (isCollection(className)) {
					if (.contains(methodInfo)) {
						if (.getStackDepth() > 0) {
							groupId = findCollectionGroup(itmtrue);
						}
else if ("iterator()Ljava/util/Iterator;".equals(methodInfo)) {
						if (.getStackDepth() > 0) {
							groupId = findCollectionGroup(itmtrue);
						}
else if ("remove(Ljava/lang/Object;)Z".equals(methodInfo)) {
						if (.getStackDepth() > 1) {
							int id = findCollectionGroup(itmtrue);
							if (id >= 0) {
    								Integer it = .get(Integer.valueOf(id));
    								Loop loop = .get(it);
    								if (loop != null) {
    									int pc = getPC();
    									if (loop.hasPC(pc)) {
    										boolean breakFollows = breakFollows(loop, !"V".equals(Type.getReturnType(signature).getSignature()));
    
    										if (!breakFollows) {
    														.addClass(this)
    														.addMethod(this)
    														.addSourceLine(this));
    										}
    									}
    								}
							    }
							}
						}
else {
						Integer numArgs = .get(methodInfo);
						if (numArgs != null) {
							if (.getStackDepth() > numArgs.intValue()) {
								int id = findCollectionGroup(itmtrue);
								if (id >= 0) {
									Integer it = .get(Integer.valueOf(id));
									if (it != null) {
										Loop loop = .get(it);
										if (loop != null) {
											int pc = getPC();
											if (loop.hasPC(pc)) {
			                                     boolean breakFollows = breakFollows(loop, !"V".equals(Type.getReturnType(signature).getSignature()));
			                                     if (!breakFollows) {
			                                         .reportBug(new BugInstance(this..name(), )
															.addClass(this)
															.addMethod(this)
			                                     }
											}
										}
									}
								}
							}
						}
					}
else if ("java/util/Iterator".equals(className) && "hasNext()Z".equals(methodInfo)) {
					if (.getStackDepth() > 0) {
						if (id != null)
							groupId = id.intValue();
					}
				}
			 } else if ((seen == ) || (seen == )) {
				if (.getStackDepth() > 1) {
					if (id == null) {
		                groupId = findCollectionGroup(itmtrue);
					}
				}
			 } else if (OpcodeUtils.isAStore(seen)) {
				if (.getStackDepth() > 0) {
					if (id != null) {
						int reg = RegisterUtils.getAStoreReg(thisseen);
						try {
                            JavaClass cls = itm.getJavaClass();
							if ((cls != null) && cls.implementationOf()) {
                                Integer regIt = Integer.valueOf(reg);
                                Iterator<IntegercurIt = .values().iterator();
                                while (curIt.hasNext()) {
                                    if (curIt.next().equals(regIt))
                                        curIt.remove();
                                }
								.put(idregIt);
							}
							if (pair != null) {
							    pair.addMember(Integer.valueOf(reg));
							}
catch (ClassNotFoundException cnfe) {
						}
else {
					    String cls = itm.getSignature();
					    if ((cls != null) && cls.startsWith("L")) {
					        cls = cls.substring(1, cls.length() - 1);
    					    if (isCollection(cls) || "java/util/Iterator".equals(cls)) {
        				        int reg = RegisterUtils.getAStoreReg(thisseen);
        				        removeFromCollectionGroup(new OpcodeStack.Item(itmreg));
        				        Iterator<Integerit = .values().iterator();
        				        while (it.hasNext()) {
        				            if (it.next().intValue() == reg) {
        				                it.remove();
        				                break;
        				            }
        				        }
    					    }
					    }
					}
				}
else if (OpcodeUtils.isALoad(seen)) {
				int reg = RegisterUtils.getALoadReg(thisseen);
				OpcodeStack.Item itm = new OpcodeStack.Item(new OpcodeStack.Item(), reg);
				groupId = findCollectionGroup(itmfalse);
else if (seen == ) {
				if (.getStackDepth() > 0) {
					if (id != null) {
						int target = getBranchTarget();
						int gotoAddr = target - 3;
						int ins = getCode().getCode()[gotoAddr];
						if (ins < 0)
							ins = 256 + ins;
						if ((ins == ) || (ins == )) {
							if (reg != null)
								.put(regnew Loop(getPC(), gotoAddr));
						}
					}
				}
			}
finally {
			TernaryPatcher.pre(seen);
			.sawOpcode(thisseen);
			TernaryPatcher.post(seen);
			if ((groupId >= 0) && (.getStackDepth() > 0)) {
				itm.setUserValue(Integer.valueOf(groupId));
			}
		}
	}
	private boolean breakFollows(Loop loopboolean needsPop) {
        byte[] code = getCode().getCode();
        int nextPC = getNextPC();
        if (needsPop) {
            int popOp = CodeByteUtils.getbyte(codenextPC++);
            if (popOp != .) {
                return false;
            }
        }
        int gotoOp = CodeByteUtils.getbyte(codenextPC);
        if ((gotoOp == .) || (gotoOp == .)) {
            int target = nextPC + CodeByteUtils.getshort(codenextPC+1);
            if (target > loop.getLoopFinish())
                return true;
        }
        return false;
	}
	private boolean isCollection(String className) {
		try {
			JavaClass cls = Repository.lookupClass(className);
catch (ClassNotFoundException cnfe) {
			return false;
		}
	}
	private static Comparable<?> getGroupElement(OpcodeStack.Item itm) {
		Comparable<?> groupElement = null;
		int reg = itm.getRegisterNumber();
		if (reg >= 0)
			groupElement = Integer.valueOf(reg);
		else {
			XField field = itm.getXField();
			if (field != null) {
                int regLoad = itm.getFieldLoadedFromRegister();
                if (regLoad >= 0)
                    groupElement = field.getName() + ":{" + regLoad + "}";
			}
		}
		return groupElement;
	}
	private int findCollectionGroup(OpcodeStack.Item itmboolean addIfNotFound) {
		if (id != null)
			return id.intValue();
		Comparable<?> groupElement = getGroupElement(itm);
		if (groupElement != null) {
			int numGroups = .size();
			for (int i = 0; i < numGroupsi++) {
				GroupPair groupPair = .get(i);
				if (groupPair.containsMember(groupElement)) {
					return i;
				}
			}
			if (addIfNotFound) {
			    GroupPair groupPair = new GroupPair(groupElementitm.getSignature());
			    .add(groupPair);
				return .size() - 1;
			}
		}
		return -1;
	}
		Comparable<?> groupElement = getGroupElement(itm);
		if (groupElement != null) {
			for (GroupPair groupPair : ) {
				if (groupPair.containsMember(groupElement)) {
				    groupPair.removeMember(groupElement);
					break;
				}
			}
		}
	}
	private void buildVariableEndScopeMap() {
	     = new HashMap<IntegerBitSet>();
        if (lvt != null) {
            int len = lvt.getLength();
            for (int i = 0; i < leni++) {
            	@SuppressWarnings("deprecation")
                LocalVariable lv = lvt.getLocalVariable(i);
                if (lv != null) {
                    Integer endPC = Integer.valueOf(lv.getStartPC() + lv.getLength());
                    BitSet vars = .get(endPC);
                    if (vars == null) {
                        vars = new BitSet();
                        .put(endPCvars);
                    }
                    vars.set(lv.getIndex());
                }
            }
        }
	}
	private void processEndOfScopes(Integer pc) {
	    BitSet endVars = .get(pc);
	    if (endVars != null) {
	        for (int i = endVars.nextSetBit(0); i >= 0; i = endVars.nextSetBit(i+1)) {
	            Integer v = Integer.valueOf(i);
	            {
        	        Iterator<GroupPairit = .iterator();
        	        while (it.hasNext()) {
        	            GroupPair groupPair = it.next();
        	            if (groupPair.containsMember(v)) {
        	                groupPair.removeMember(v);
        	            }
        	        }
	            }
	            {
	                Iterator<Integerit = .values().iterator();
	                while (it.hasNext()) {
	                    if (v.equals(it.next())) {
	                        it.remove();
	                    }
	                }
	            }
    	    }
	    }
	}
	static class Loop
	{
		public int loopStart;
		public int loopFinish;
		public Loop(int startint finish) {
			 = start;
			 = finish;
		}
		int getLoopFinish() {
			return ;
		}
		int getLoopStart() {
			return ;
		}
		boolean hasPC(int pc) {
			return ( <= pc) && (pc <= );
		}
        @Override
        public String toString() {
        	return ToString.build(this);
        }
	}
	static class GroupPair {
	    private final Set<Comparable<?>> groupMembers;
	    private final String colClass;
	    
	    public GroupPair(Comparable<?> memberString cls) {
	         = new HashSet<Comparable<?>>();
	        .add(member);
	         = cls;
	    }
	    
	    void addMember(Comparable<?> member) {
	        .add(member);
	    }
	    
	    void removeMember(Comparable<?> member) {
            .remove(member);
        }
	    
	    boolean containsMember(Comparable<?> member) {
	        return .contains(member);
	    }
	    
	    boolean isStandardCollection() {
	        return ( == null) || !.contains("/concurrent/");
	    }
	    
	    @Override
	    public String toString() {
	    	return ToString.build(this);
	    }
	}
New to GrepCode? Check out our FAQ X