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

📄 hierarchy.java

📁 一个查找java程序里bug的程序的源代码,该程序本身也是java写的,对提高java编程水平很有用
💻 JAVA
字号:
/* * Bytecode Analysis Framework * Copyright (C) 2003,2004 University of Maryland *  * 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 edu.umd.cs.findbugs.ba;import org.apache.bcel.Constants;import org.apache.bcel.Repository;import org.apache.bcel.classfile.ExceptionTable;import org.apache.bcel.classfile.Field;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.Method;import org.apache.bcel.generic.*;/** * Facade for class hierarchy queries. * These typically access the class hierarchy using * the {@link org.apache.bcel.Repository} class.  Callers should generally * expect to handle ClassNotFoundException for when referenced * classes can't be found. * * @author David Hovemeyer */public class Hierarchy {	/**	 * Type of java.lang.Exception.	 */	public static final ObjectType EXCEPTION_TYPE = new ObjectType("java.lang.Exception");	/**	 * Type of java.lang.Error.	 */	public static final ObjectType ERROR_TYPE = new ObjectType("java.lang.Error");	/**	 * Type of java.lang.RuntimeException.	 */	public static final ObjectType RUNTIME_EXCEPTION_TYPE = new ObjectType("java.lang.RuntimeException");	/**	 * Determine whether one class (or reference type) is a subtype	 * of another.	 *	 * @param clsName                    the name of the class or reference type	 * @param possibleSupertypeClassName the name of the possible superclass	 * @return true if clsName is a subtype of possibleSupertypeClassName,	 *         false if not	 */	public static boolean isSubtype(String clsName, String possibleSupertypeClassName) throws ClassNotFoundException {		ObjectType cls = new ObjectType(clsName);		ObjectType superCls = new ObjectType(possibleSupertypeClassName);		return isSubtype(cls, superCls);	}	/**	 * Determine if one reference type is a subtype of another.	 *	 * @param t                 a reference type	 * @param possibleSupertype the possible supertype	 * @return true if t is a subtype of possibleSupertype,	 *         false if not	 */	public static boolean isSubtype(ReferenceType t, ReferenceType possibleSupertype) throws ClassNotFoundException {		return t.isAssignmentCompatibleWith(possibleSupertype);	}	/**	 * Determine if the given ObjectType reference represents	 * a <em>universal</em> exception handler.  That is,	 * one that will catch any kind of exception.	 *	 * @param catchType the ObjectType of the exception handler	 * @return true if catchType is null, or if catchType is	 *         java.lang.Throwable	 */	public static boolean isUniversalExceptionHandler(ObjectType catchType) {		return catchType == null || catchType.equals(Type.THROWABLE);	}	/**	 * Determine if the given ObjectType refers to an unchecked	 * exception (RuntimeException or Error).	 */	public static boolean isUncheckedException(ObjectType type) throws ClassNotFoundException {		return isSubtype(type, RUNTIME_EXCEPTION_TYPE) || isSubtype(type, ERROR_TYPE);	}	/**	 * Determine if method whose name and signature is specified	 * is a monitor wait operation.	 *	 * @param methodName name of the method	 * @param methodSig  signature of the method	 * @return true if the method is a monitor wait, false if not	 */	public static boolean isMonitorWait(String methodName, String methodSig) {		return methodName.equals("wait") &&		        (methodSig.equals("()V") || methodSig.equals("(J)V") || methodSig.equals("(JI)V"));	}	/**	 * Determine if method whose name and signature is specified	 * is a monitor notify operation.	 *	 * @param methodName name of the method	 * @param methodSig  signature of the method	 * @return true if the method is a monitor notify, false if not	 */	public static boolean isMonitorNotify(String methodName, String methodSig) {		return (methodName.equals("notify") || methodName.equals("notifyAll")) &&		        methodSig.equals("()V");	}	/**	 * Look up the method referenced by given InvokeInstruction.	 * This method does <em>not</em> look for implementations in	 * super or subclasses according to the virtual dispatch rules.	 *	 * @param inv the InvokeInstruction	 * @param cpg the ConstantPoolGen used by the class the InvokeInstruction belongs to	 * @return the Method, or null if no such method is defined in the class	 */	public static Method findExactMethod(InvokeInstruction inv, ConstantPoolGen cpg) throws ClassNotFoundException {		String className = inv.getClassName(cpg);		String methodName = inv.getName(cpg);		String methodSig = inv.getSignature(cpg);		JavaClass jclass = Repository.lookupClass(className);		return findMethod(jclass, methodName, methodSig);	}	/**	 * Get the method which serves as a "prototype" for the	 * given InvokeInstruction.  The "prototype" is the method	 * which defines the contract for the invoked method,	 * in particular the declared list of exceptions that the	 * method can throw.	 * <p/>	 * <ul>	 * <li> For invokestatic and invokespecial, this is simply an	 * exact lookup.	 * <li> For invokevirtual, the named class is searched,	 * followed by superclasses  up to the root of the object	 * hierarchy (java.lang.Object).	 * <li> For invokeinterface, the named class is searched,	 * followed by all interfaces transitively declared by the class.	 * (Question: is the order important here? Maybe the VM spec	 * requires that the actual interface desired is given,	 * so the extended lookup will not be required. Should check.)	 * </ul>	 *	 * @param inv the InvokeInstruction	 * @param cpg the ConstantPoolGen used by the class the InvokeInstruction belongs to	 * @return the Method, or null if no matching method can be found	 */	public static Method findPrototypeMethod(InvokeInstruction inv, ConstantPoolGen cpg)	        throws ClassNotFoundException {		Method m = null;		String className = inv.getClassName(cpg);		String methodName = inv.getName(cpg);		String methodSig = inv.getSignature(cpg);		// Find the method		if (inv instanceof INVOKESTATIC || inv instanceof INVOKESPECIAL) {			// Non-virtual dispatch			m = findExactMethod(inv, cpg);			if (m == null) {				// XXX/*				System.out.println("Could not resolve " + inv + " in " +					SignatureConverter.convertMethodSignature(inv, cpg));*/			} else if (inv instanceof INVOKESTATIC && !m.isStatic()) {				m = null;			}		} else if (inv instanceof INVOKEVIRTUAL) {			// Virtual dispatch			m = findMethod(Repository.lookupClass(className), methodName, methodSig);			if (m == null) {				JavaClass[] superClassList = Repository.getSuperClasses(className);				m = findMethod(superClassList, methodName, methodSig);			}		} else if (inv instanceof INVOKEINTERFACE) {			// Interface dispatch			m = findMethod(Repository.lookupClass(className), methodName, methodSig);			if (m == null) {				JavaClass[] interfaceList = Repository.getInterfaces(className);				m = findMethod(interfaceList, methodName, methodSig);			}		}		return m;	}	/**	 * Find the declared exceptions for the method called	 * by given instruction.	 *	 * @param inv the InvokeInstruction	 * @param cpg the ConstantPoolGen used by the class the InvokeInstruction belongs to	 * @return array of ObjectTypes of thrown exceptions, or null	 *         if we can't find the list of declared exceptions	 */	public static ObjectType[] findDeclaredExceptions(InvokeInstruction inv, ConstantPoolGen cpg)	        throws ClassNotFoundException {		Method m = findPrototypeMethod(inv, cpg);		if (m == null)			return null;		ExceptionTable exTable = m.getExceptionTable();		if (exTable == null)			return new ObjectType[0];		String[] exNameList = exTable.getExceptionNames();		ObjectType[] result = new ObjectType[exNameList.length];		for (int i = 0; i < exNameList.length; ++i) {			result[i] = new ObjectType(exNameList[i]);		}		return result;	}	/**	 * Find a method in given class.	 *	 * @param javaClass  the class	 * @param methodName the name of the method	 * @param methodSig  the signature of the method	 * @return the Method, or null if no such method exists in the class	 */	public static Method findMethod(JavaClass javaClass, String methodName, String methodSig) {		Method[] methodList = javaClass.getMethods();		for (int i = 0; i < methodList.length; ++i) {			Method method = methodList[i];			if (method.getName().equals(methodName) && method.getSignature().equals(methodSig))				return method;		}		return null;	}	/**	 * Find a method in given list of classes,	 * searching the classes in order.	 *	 * @param classList  list of classes in which to search	 * @param methodName the name of the method	 * @param methodSig  the signature of the method	 * @return the Method, or null if no such method exists in the class	 */	public static Method findMethod(JavaClass[] classList, String methodName, String methodSig) {		Method m = null;		for (int i = 0; i < classList.length; ++i) {			JavaClass cls = classList[i];			if ((m = findMethod(cls, methodName, methodSig)) != null)				break;		}		return m;	}	/**	 * Find a field with given name defined in given class.	 *	 * @param className the name of the class	 * @param fieldName the name of the field	 * @return the Field, or null if no such field could be found	 */	public static Field findField(String className, String fieldName) throws ClassNotFoundException {		JavaClass jclass = Repository.lookupClass(className);		while (jclass != null) {			Field[] fieldList = jclass.getFields();			for (int i = 0; i < fieldList.length; ++i) {				Field field = fieldList[i];				if (field.getName().equals(fieldName)) {					return field;				}			}			jclass = jclass.getSuperClass();		}		return null;	}/*	public static JavaClass findClassDefiningField(String className, String fieldName, String fieldSig)		throws ClassNotFoundException {		JavaClass jclass = Repository.lookupClass(className);		while (jclass != null) {			Field[] fieldList = jclass.getFields();			for (int i = 0; i < fieldList.length; ++i) {				Field field = fieldList[i];				if (field.getName().equals(fieldName) && field.getSignature().equals(fieldSig)) {					return jclass;				}			}				jclass = jclass.getSuperClass();		}		return null;	}*/	/**	 * Look up a field with given name and signature in given class,	 * returning it as an {@link XField XField} object.	 * If a field can't be found in the immediate class,	 * its superclass is search, and so forth.	 *	 * @param className name of the class through which the field	 *                  is referenced	 * @param fieldName name of the field	 * @param fieldSig  signature of the field	 * @return an XField object representing the field, or null if no such field could be found	 */	public static XField findXField(String className, String fieldName, String fieldSig)	        throws ClassNotFoundException {		JavaClass classDefiningField = Repository.lookupClass(className);		Field field = null;		loop:			while (classDefiningField != null) {				Field[] fieldList = classDefiningField.getFields();				for (int i = 0; i < fieldList.length; ++i) {					field = fieldList[i];					if (field.getName().equals(fieldName) && field.getSignature().equals(fieldSig)) {						break loop;					}				}				classDefiningField = classDefiningField.getSuperClass();			}		if (classDefiningField == null)			return null;		else {			String realClassName = classDefiningField.getClassName();			int accessFlags = field.getAccessFlags();			return field.isStatic()			        ? (XField) new StaticField(realClassName, fieldName, fieldSig, accessFlags)			        : (XField) new InstanceField(realClassName, fieldName, fieldSig, accessFlags);		}	}	/**	 * Look up the field referenced by given FieldInstruction,	 * returning it as an {@link XField XField} object.	 *	 * @param fins the FieldInstruction	 * @param cpg  the ConstantPoolGen used by the class containing the instruction	 * @return an XField object representing the field, or null	 *         if no such field could be found	 */	public static XField findXField(FieldInstruction fins, ConstantPoolGen cpg)	        throws ClassNotFoundException {		String className = fins.getClassName(cpg);		String fieldName = fins.getFieldName(cpg);		String fieldSig = fins.getSignature(cpg);		XField xfield = findXField(className, fieldName, fieldSig);		short opcode = fins.getOpcode();		if (xfield != null &&		        xfield.isStatic() == (opcode == Constants.GETSTATIC || opcode == Constants.PUTSTATIC))			return xfield;		else			return null;	}	/**	 * Determine whether the given INVOKESTATIC instruction	 * is an inner-class field accessor method.	 * @param inv the INVOKESTATIC instruction	 * @param cpg the ConstantPoolGen for the method	 * @return true if the instruction is an inner-class field accessor, false if not	 */	public static boolean isInnerClassAccess(INVOKESTATIC inv, ConstantPoolGen cpg) {		String methodName = inv.getName(cpg);		return methodName.startsWith("access$");	}	/**	 * Get the InnerClassAccess for access method called	 * by given INVOKESTATIC.	 * @param inv the INVOKESTATIC instruction	 * @param cpg the ConstantPoolGen for the method	 * @return the InnerClassAccess, or null if the instruction is not	 *    an inner-class access	 */	public static InnerClassAccess getInnerClassAccess(INVOKESTATIC inv, ConstantPoolGen cpg)			throws ClassNotFoundException {		String className = inv.getClassName(cpg);		String methodName = inv.getName(cpg);		String methodSig = inv.getSignature(cpg);		InnerClassAccess access = InnerClassAccessMap.instance().getInnerClassAccess(className, methodName);		return (access != null && access.getMethodSignature().equals(methodSig))			? access			: null;	}}// vim:ts=4

⌨️ 快捷键说明

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