Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * fb-contrib - Auxiliary detectors for Java programs
   * Copyright (C) 2005-2015 Kevin Lubick
   * 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.Map;
 import java.util.Set;
 
 
 
looks for executors that are never shutdown, which will not allow the application to terminate
 
 public class HangingExecutors extends BytecodeScanningDetector {
 
 	private static final Set<StringhangableSig = new HashSet<String>();
 
 	static {
 		.add("Ljava/util/concurrent/ExecutorService;");
 		.add("Ljava/util/concurrent/AbstractExecutorService;");
 		.add("Ljava/util/concurrent/ForkJoinPool;");
 		.add("Ljava/util/concurrent/ScheduledThreadPoolExecutor;");
 		.add("Ljava/util/concurrent/ThreadPoolExecutor;");
 	}
 
 
 	private static final Set<StringshutdownMethods = new HashSet<String>();
 
 	static {
 		.add("shutdown");
 		.add("shutdownNow");
 	}
 
 
 	private final BugReporter bugReporter;
 	private OpcodeStack stack;
 	private String methodName;
 
 
 
 
 	public HangingExecutors(BugReporter reporter) {
 		this.=reporter;
 		this. = new LocalHangingExecutor(thisreporter);
 	}


finds ExecutorService objects that don't get a call to the terminating methods, and thus, never appear to be shutdown properly (the threads exist until shutdown is called)

Parameters:
classContext the class context object of the currently parsed java class
 
 	public void visitClassContext(ClassContext classContext) {
		try {
				 = new OpcodeStack();
				super.visitClassContext(classContext);
			}
finally {
			 = null;
		}
	}
	private void parseFieldsForHangingCandidates(ClassContext classContext) {
		JavaClass cls = classContext.getJavaClass();
		Field[] fields = cls.getFields();
		for (Field f : fields) {
			String sig = f.getSignature();
			if (.contains(sig)) {
			}
		}
	}
			AnnotationPriority fieldAn = entry.getValue();
			if (fieldAn != null) {
				.addClass(this)
				.addField(fieldAn.annotation)
				.addField(entry.getKey()));
			}
		}
	}

implements the visitor to reset the opcode stack

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

implements the visitor to collect the method name

Parameters:
obj the context object of the currently parsed method
	public void visitMethod(Method obj) {
	}

Browses for calls to shutdown() and shutdownNow(), and if they happen, remove the hanging candidate, as there is a chance it will be called.

Parameters:
seen the opcode of the currently parsed instruction
	public void sawOpcode(int seen) {
		{
			return;
		}
		try {
			if ((seen == ) || (seen == )) {
				int argCount = Type.getArgumentTypes(sig).length;
				if (.getStackDepth() > argCount) {
					OpcodeStack.Item invokeeItem = .getStackItem(argCount);
					XField fieldOnWhichMethodIsInvoked = invokeeItem.getXField();
					if (fieldOnWhichMethodIsInvoked != null) {		
						removeCandidateIfShutdownCalled(fieldOnWhichMethodIsInvoked);
						addExemptionIfShutdownCalled(fieldOnWhichMethodIsInvoked);
				}
			}
			//TODO Should not include private methods
			else if (seen == ) {
			}
			else if (seen == ) {
				if (f != null)
			}
			else if (seen == ) {
				//indicates a null check, which means that we get an exemption until the end of the branch
				OpcodeStack.Item nullCheckItem = .getStackItem(0);
				XField fieldWhichWasNullChecked = nullCheckItem.getXField();
				if (fieldWhichWasNullChecked != null) {
					.put(fieldWhichWasNullCheckedgetPC() + getBranchOffset());
				}
			}
		}
		finally {
			.sawOpcode(thisseen);
		}
	}
	private void lookForCustomThreadFactoriesInConstructors(int seen) {
		try {
			if (seen == ) {
				if (f != null && .contains(f.getSignature())){
					//look at the top of the stack, get the arguments passed into the function that was called
					//and then pull out the types.
					//if the last type is a ThreadFactory, set the priority to low
					if (method != null) {
						Type[] argumentTypes = Type.getArgumentTypes(method.getSignature());
						if (argumentTypes.length != 0) {
							if ("Ljava/util/concurrent/ThreadFactory;".equals(argumentTypes[argumentTypes.length-1].getSignature())) {
								if (ap != null) {
									ap.priority = ;
								}
							}
						}
					}
				}
			}		
		}
		finally {
			.sawOpcode(thisseen);
		}
	}
	private void reportOverwrittenField(XField f) {
		if ("Ljava/util/concurrent/ExecutorService;".equals(f.getSignature()) && !checkException(f)) {
			.addClass(this)
			.addMethod(this)
		//after it's been replaced, it no longer uses its exemption. 
	}
	private boolean checkException(XField f) {
			return false;
		int i = .get(f).intValue();
		return i == -1 || getPC() < i;
	}
	private void removeFieldsThatGetReturned() {
		if (.getStackDepth() > 0) {
			OpcodeStack.Item returnItem = .getStackItem(0); //top thing on the stack was the variable being returned
			XField field = returnItem.getXField();
			if (field != null) {
			}
		}
	}
	private void addExemptionIfShutdownCalled(XField fieldOnWhichMethodIsInvoked) {
		String methodBeingInvoked = getNameConstantOperand();
		if (.contains(methodBeingInvoked)) {
			.put(fieldOnWhichMethodIsInvoked, -1);
		}
	}
	private void removeCandidateIfShutdownCalled(XField fieldOnWhichMethodIsInvoked) {
		if (.containsKey(fieldOnWhichMethodIsInvoked)) {
			String methodBeingInvoked = getNameConstantOperand();
			if (.contains(methodBeingInvoked)) {
				.remove(fieldOnWhichMethodIsInvoked);
			}
		}
	}
	private static class AnnotationPriority {
		AnnotationPriority(FieldAnnotation annotationint priority) {
			this. = annotation;
			this. = priority;
		}
		public String toString() {
			return ToString.build(this);
		}
	}
	private static final Map<StringSet<String>> watchedClassMethods = new HashMap<StringSet<String>>();
	private static final Map<StringIntegersyncCtors = new HashMap<StringInteger>();
	static {
		Set<StringforExecutors = new HashSet<String>();
		forExecutors.add("newCachedThreadPool");
		forExecutors.add("newFixedThreadPool");
		forExecutors.add("newScheduledThreadPool");
		forExecutors.add("newSingleThreadExecutor");
		.put("java/util/concurrent/Executors"forExecutors);
		.put("java/util/concurrent/ThreadPoolExecutor", Integer.valueOf(.));
		.put("java/util/concurrent/ScheduledThreadPoolExecutor", Integer.valueOf(.));
	}
	private final BugReporter bugReporter;
	private final Detector delegatingDetector;
	public LocalHangingExecutor(Detector delegatingDetectorBugReporter reporter) {
		this. = reporter;
		this. = delegatingDetector;
	}
		return ;
	}
	}
	protected void reportBug(RegisterInfo cri) {
		//very important to report the bug under the top, parent detector, otherwise it gets filtered out
		.reportBug(new BugInstance("HES_LOCAL_EXECUTOR_SERVICE")
		.addClass(this)
		.addMethod(this)
	}
	public void visitClassContext(ClassContext classContext) {
		super.visitClassContext(classContext);
	}
	public void visitCode(Code obj) {
		super.visitCode(obj);
	}
	public void visitMethod(Method obj) {
		super.visitMethod(obj);
	}
New to GrepCode? Check out our FAQ X