⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 findhemismatch.java

📁 A static analysis tool to find bugs in Java programs
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
				if (hasEqualsObject && inheritedEqualsIsAbstract)					priority++;				if (hasFields)					priority--;				if (equalsMethodIsInstanceOfEquals || !hasEqualsObject)					priority += 2;				else if (obj.isAbstract())					priority++;				BugInstance bug = new BugInstance(this,						"HE_EQUALS_NO_HASHCODE", priority)						.addClass(getDottedClassName());				if (equalsMethod != null)					bug.addMethod(equalsMethod);				bugReporter.reportBug(bug);			}		}		if (!hasHashCode && !hasEqualsObject && !hasEqualsSelf				&& !usesDefaultEquals && usesDefaultHashCode				&& !obj.isAbstract() && classThatDefinesEqualsIsAbstract) {			BugInstance bug = new BugInstance(this,					"HE_INHERITS_EQUALS_USE_HASHCODE", NORMAL_PRIORITY)					.addClass(getDottedClassName());			if (equalsMethod != null)				bug.addMethod(equalsMethod);			bugReporter.reportBug(bug);		}	}	@Override	public void visit(JavaClass obj) {		extendsObject = getDottedSuperclassName().equals("java.lang.Object");		hasFields = false;		hasHashCode = false;		hasCompareToObject = false;		hasCompareToSelf = false;		hasEqualsObject = false;		hasEqualsSelf = false;		hashCodeIsAbstract = false;		equalsObjectIsAbstract = false;		equalsMethodIsInstanceOfEquals = false;		equalsMethod = null;		compareToMethod = null;		compareToSelfMethod = null;		compareToObjectMethod = null;		hashCodeMethod = null;	}	@Override	public void visit(Field obj) {		int accessFlags = obj.getAccessFlags();		if ((accessFlags & ACC_STATIC) != 0)			return;		if (!obj.getName().startsWith("this$"))			hasFields = true;	}	@Override	public void visit(Method obj) {		stack.resetForMethodEntry(this);		int accessFlags = obj.getAccessFlags();		if ((accessFlags & ACC_STATIC) != 0)			return;		String name = obj.getName();		String sig = obj.getSignature();		if ((accessFlags & ACC_ABSTRACT) != 0) {			if (name.equals("equals")					&& sig.equals("(L" + getClassName() + ";)Z")) {				bugReporter.reportBug(new BugInstance(this, "EQ_ABSTRACT_SELF",						LOW_PRIORITY).addClass(getDottedClassName()));				return;			} else if (name.equals("compareTo")					&& sig.equals("(L" + getClassName() + ";)I")) {				bugReporter.reportBug(new BugInstance(this, "CO_ABSTRACT_SELF",						LOW_PRIORITY).addClass(getDottedClassName()));				return;			}		}		boolean sigIsObject = sig.equals("(Ljava/lang/Object;)Z");		if (name.equals("hashCode") && sig.equals("()I")) {			hasHashCode = true;			if (obj.isAbstract())				hashCodeIsAbstract = true;			hashCodeMethod = MethodAnnotation.fromVisitedMethod(this);			// System.out.println("Found hashCode for " + betterClassName);		} else if (name.equals("equals")) {			if (sigIsObject) {				equalsMethod = MethodAnnotation.fromVisitedMethod(this);				hasEqualsObject = true;				if (obj.isAbstract())					equalsObjectIsAbstract = true;				else if (!obj.isNative()) {					Code code = obj.getCode();					byte[] codeBytes = code.getCode();					if ((codeBytes.length == 5 && (codeBytes[1] & 0xff) == INSTANCEOF)							|| (codeBytes.length == 15									&& (codeBytes[1] & 0xff) == INSTANCEOF && (codeBytes[11] & 0xff) == INVOKESPECIAL)) {						equalsMethodIsInstanceOfEquals = true;					}				}			} else if (sig.equals("(L" + getClassName() + ";)Z")) {				hasEqualsSelf = true;				if (equalsMethod == null)					equalsMethod = MethodAnnotation.fromVisitedMethod(this);			}		} else if (name.equals("compareTo")) {			MethodAnnotation tmp  = MethodAnnotation.fromVisitedMethod(this);			if (sig.equals("(Ljava/lang/Object;)I")) {				hasCompareToObject = true;				compareToObjectMethod = compareToMethod = tmp;			}			else if (sig.equals("(L" + getClassName() + ";)I")) {				hasCompareToSelf = true;				compareToSelfMethod = compareToMethod = tmp;			}		}	}	Method findMethod(JavaClass clazz, String name, String sig) {		Method[] m = clazz.getMethods();		for (Method aM : m)			if (aM.getName().equals(name) && aM.getSignature().equals(sig))				return aM;		return null;	}	@Override	public void sawOpcode(int seen) {		stack.mergeJumps(this);		if (seen == INVOKEVIRTUAL) {			String className = getClassConstantOperand();			if (className.equals("java/util/Map") || className.equals("java/util/HashMap") 					|| className.equals("java/util/LinkedHashMap")					|| className.equals("java/util/concurrent/ConcurrentHashMap") ) {				if (getNameConstantOperand().equals("put")						&& getSigConstantOperand()						.equals("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")						&& stack.getStackDepth() >= 3) check(1);				else if ((getNameConstantOperand().equals("get") || getNameConstantOperand().equals("remove"))						&& getSigConstantOperand()						.equals("(Ljava/lang/Object;)Ljava/lang/Object;")						&& stack.getStackDepth() >= 2) check(0);			}	else if (className.equals("java/util/Set") || className.equals("java/util/HashSet")  ) {				if (getNameConstantOperand().equals("add") || getNameConstantOperand().equals("contains") || getNameConstantOperand().equals("remove")						&& getSigConstantOperand()						.equals("(Ljava/lang/Object;)Z")						&& stack.getStackDepth() >= 2) check(0);			}		}		stack.sawOpcode(this, seen);	}	private void check(int pos) {		OpcodeStack.Item item = stack.getStackItem(pos);		JavaClass type = null;		try {			type = item.getJavaClass();		} catch (ClassNotFoundException e) {			AnalysisContext.reportMissingClass(e);		}		if (type == null) return;		 int priority = NORMAL_PRIORITY;		if (getClassConstantOperand().indexOf("Hash") >= 0) priority--;		if (!AnalysisContext.currentAnalysisContext().getSubtypes().isApplicationClass(type)) priority++;		if (type.isAbstract() || type.isInterface()) priority++;		potentialBugs.put(type.getClassName(), 				new BugInstance(this, "HE_USE_OF_UNHASHABLE_CLASS",priority)		.addClassAndMethod(this)		.addTypeOfNamedClass(type.getClassName()).describe(TypeAnnotation.UNHASHABLE_ROLE)		.addTypeOfNamedClass(getClassConstantOperand())		.addSourceLine(this));	}	static final Pattern mapPattern = Pattern.compile("HashMap<L([^;<]*);");	static final Pattern hashTablePattern = Pattern.compile("Hashtable<L([^;<]*);");	static final Pattern setPattern = Pattern.compile("HashSet<L([^;<]*);");	@CheckForNull String findHashedClassInSignature(String sig) {		Matcher m = mapPattern.matcher(sig);		if (m.find())			return m.group(1).replace('/','.');		m = hashTablePattern.matcher(sig);		if (m.find()) return m.group(1).replace('/','.');		m = setPattern.matcher(sig);		if (m.find()) return m.group(1).replace('/','.');;		return null;	}	@Override	public void visit(Signature obj) {		String sig = obj.getSignature();		String className = findHashedClassInSignature(sig);		if (className == null) return;		JavaClass type = null;		try {			type = Repository.lookupClass(className);		} catch (ClassNotFoundException e) {			AnalysisContext.reportMissingClass(e);		}		if (type == null) return;		int priority = NORMAL_PRIORITY;		if (sig.indexOf("Hash") >= 0) priority--;		if (type.isAbstract() || type.isInterface()) priority++;		if (!AnalysisContext.currentAnalysisContext().getSubtypes().isApplicationClass(type)) priority++;		BugInstance bug = null;		if (visitingField())			bug = new BugInstance(this, "HE_USE_OF_UNHASHABLE_CLASS",					priority).addClass(this).addVisitedField(							this).addTypeOfNamedClass(className).describe(TypeAnnotation.UNHASHABLE_ROLE);		else if (visitingMethod())			bug = new BugInstance(this, "HE_USE_OF_UNHASHABLE_CLASS",					priority).addClassAndMethod(this).addTypeOfNamedClass(className).describe(TypeAnnotation.UNHASHABLE_ROLE);		else			bug = new BugInstance(this, "HE_USE_OF_UNHASHABLE_CLASS",					priority).addClass(this).addClass(this).addTypeOfNamedClass(className).describe(TypeAnnotation.UNHASHABLE_ROLE);		potentialBugs.put(className, bug);	}	@Override	public void report() {		for(Map.Entry<String, BugInstance> e : potentialBugs.entrySet()) {			if (!isHashableClassName(e.getKey())) {				BugInstance bug = e.getValue();				bugReporter.reportBug(bug);			}		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -