📄 hierarchy.java
字号:
TypeFrame typeFrame, ConstantPoolGen cpg) throws DataflowAnalysisException, ClassNotFoundException { short opcode = invokeInstruction.getOpcode(); if (opcode == Constants.INVOKESTATIC) { HashSet<JavaClassAndMethod> result = new HashSet<JavaClassAndMethod>(); JavaClassAndMethod targetMethod = findInvocationLeastUpperBound(invokeInstruction, cpg, CONCRETE_METHOD); if (targetMethod != null) { result.add(targetMethod); } return result; } if (!typeFrame.isValid()) { return new HashSet<JavaClassAndMethod>(); } Type receiverType; boolean receiverTypeIsExact; if (opcode == Constants.INVOKESPECIAL) { // invokespecial instructions are dispatched to EXACTLY // the class specified by the instruction receiverType = ObjectTypeFactory.getInstance(invokeInstruction.getClassName(cpg)); receiverTypeIsExact = false; // Doesn't actually matter } else { // For invokevirtual and invokeinterface instructions, we have // virtual dispatch. By taking the receiver type (which may be a // subtype of the class specified by the instruction), // we may get a more precise set of call targets. int instanceStackLocation = typeFrame.getInstanceStackLocation(invokeInstruction, cpg); receiverType = typeFrame.getStackValue(instanceStackLocation); if (!(receiverType instanceof ReferenceType)) { return new HashSet<JavaClassAndMethod>(); } receiverTypeIsExact = typeFrame.isExact(instanceStackLocation); } if (DEBUG_METHOD_LOOKUP) { System.out.println("[receiver type is " + receiverType + ", " + (receiverTypeIsExact ? "exact]" : " not exact]")); } return resolveMethodCallTargets((ReferenceType) receiverType, invokeInstruction, cpg, receiverTypeIsExact); } /** * Resolve possible instance method call targets. * Assumes that invokevirtual and invokeinterface methods may * call any subtype of the receiver class. * * @param receiverType type of the receiver object * @param invokeInstruction the InvokeInstruction * @param cpg the ConstantPoolGen * @return Set of methods which might be called * @throws ClassNotFoundException */ public static Set<JavaClassAndMethod> resolveMethodCallTargets( ReferenceType receiverType, InvokeInstruction invokeInstruction, ConstantPoolGen cpg ) throws ClassNotFoundException { return resolveMethodCallTargets(receiverType, invokeInstruction, cpg, false); } /** * Resolve possible instance method call targets. * * @param receiverType type of the receiver object * @param invokeInstruction the InvokeInstruction * @param cpg the ConstantPoolGen * @param receiverTypeIsExact if true, the receiver type is known exactly, * which should allow a precise result * @return Set of methods which might be called * @throws ClassNotFoundException */ public static Set<JavaClassAndMethod> resolveMethodCallTargets( ReferenceType receiverType, InvokeInstruction invokeInstruction, ConstantPoolGen cpg, boolean receiverTypeIsExact ) throws ClassNotFoundException { HashSet<JavaClassAndMethod> result = new HashSet<JavaClassAndMethod>(); if (invokeInstruction.getOpcode() == Constants.INVOKESTATIC) throw new IllegalArgumentException(); String methodName = invokeInstruction.getName(cpg); String methodSig = invokeInstruction.getSignature(cpg); // Array method calls aren't virtual. // They should just resolve to Object methods. if (receiverType instanceof ArrayType) { JavaClass javaLangObject = AnalysisContext.currentAnalysisContext().lookupClass("java.lang.Object"); JavaClassAndMethod classAndMethod = findMethod(javaLangObject, methodName, methodSig, INSTANCE_METHOD); if (classAndMethod != null) result.add(classAndMethod); return result; } AnalysisContext analysisContext = AnalysisContext.currentAnalysisContext(); // Get the receiver class. JavaClass receiverClass = analysisContext.lookupClass( ((ObjectType) receiverType).getClassName()); // Figure out the upper bound for the method. // This is what will be called if this is not a virtual call site. JavaClassAndMethod upperBound = findMethod(receiverClass, methodName, methodSig, CONCRETE_METHOD); if (upperBound == null) { // Try superclasses JavaClass[] superClassList = receiverClass.getSuperClasses(); upperBound = findMethod(superClassList, methodName, methodSig, CONCRETE_METHOD); } if (upperBound != null) { if (DEBUG_METHOD_LOOKUP) { System.out.println("Adding upper bound: " + SignatureConverter.convertMethodSignature(upperBound.getJavaClass(), upperBound.getMethod())); } result.add(upperBound); } // Is this a virtual call site? boolean virtualCall = invokeInstruction.getOpcode() != Constants.INVOKESPECIAL && !receiverTypeIsExact; if (virtualCall) { // This is a true virtual call: assume that any concrete // subtype method may be called. Set<JavaClass> subTypeSet = analysisContext.getSubtypes().getTransitiveSubtypes(receiverClass); for (JavaClass subtype : subTypeSet) { JavaClassAndMethod concreteSubtypeMethod = findMethod(subtype, methodName, methodSig, CONCRETE_METHOD); if (concreteSubtypeMethod != null) { result.add(concreteSubtypeMethod); } } } return result; }// // /**// * Return whether or not the given method is concrete.// * // * @param xmethod the method// * @return true if the method is concrete, false otherwise// */// public static boolean isConcrete(XMethod xmethod) {// int accessFlags = xmethod.getAccessFlags();// return (accessFlags & Constants.ACC_ABSTRACT) == 0// && (accessFlags & Constants.ACC_NATIVE) == 0;// } /** * 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 (Field field : fieldList) { 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 (Field aFieldList : fieldList) { field = aFieldList; if (field.getName().equals(fieldName) && field.getSignature().equals(fieldSig)) { break loop; } } classDefiningField = classDefiningField.getSuperClass(); } if (classDefiningField == null || field == 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, @NonNull 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 = AnalysisContext.currentAnalysisContext() .getInnerClassAccessMap().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 + -