/** * <p>Find the least upper bound method in the class hierarchy which could be * called by the given InvokeInstruction. One reason this method is useful * is that it indicates which declared exceptions are thrown by the called * methods.</p> * <ul> * <li>For invokespecial, this is simply an exact lookup.</li> * <li>For invokestatic and invokevirtual, the named class is searched, * followed by superclasses up to the root of the object hierarchy * (java.lang.Object). Yes, invokestatic really is declared to check * superclasses. See VMSpec, 2nd ed, sec. 5.4.3.3.</li> * <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.)</li> * </ul> * * @param inv * the InvokeInstruction * @param cpg * the ConstantPoolGen used by the class the InvokeInstruction * belongs to * @return the JavaClassAndMethod, or null if no matching method can be * found */ public static @CheckForNull JavaClassAndMethod findInvocationLeastUpperBound(InvokeInstruction inv, ConstantPoolGen cpg) throws ClassNotFoundException { return findInvocationLeastUpperBound(inv, cpg, ANY_METHOD); }
public static @CheckForNull JavaClassAndMethod findInvocationLeastUpperBound(JavaClass jClass, String methodName, String methodSig, JavaClassAndMethodChooser methodChooser, boolean invokeInterface) throws ClassNotFoundException { JavaClassAndMethod result = findMethod(jClass, methodName, methodSig, methodChooser); if (result != null) { return result; } if (invokeInterface) { for (JavaClass i : jClass.getInterfaces()) { result = findInvocationLeastUpperBound(i, methodName, methodSig, methodChooser, invokeInterface); if (result != null) { return null; } } } else { JavaClass sClass = jClass.getSuperClass(); if (sClass != null) { return findInvocationLeastUpperBound(sClass, methodName, methodSig, methodChooser, invokeInterface); } } return null; }
return findInvocationLeastUpperBound(jClass, methodName, methodSig, methodChooser, opcode == Const.INVOKEINTERFACE);
JavaClassAndMethod targetMethod = findInvocationLeastUpperBound(invokeInstruction, cpg, CONCRETE_METHOD); if (targetMethod != null) { result.add(targetMethod);
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, ClassNotFoundException, DataflowAnalysisException { CFG cfg = classContext.getCFG(method); for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Location location = i.next(); Instruction ins = location.getHandle().getInstruction(); if (ins instanceof InvokeInstruction) { if (TARGET_METHOD != null && !((InvokeInstruction) ins).getMethodName(classContext.getConstantPoolGen()).equals(TARGET_METHOD)) { continue; } System.out.println("\n*******************************************************\n"); System.out.println("Method invocation: " + location.getHandle()); System.out.println("\tInvoking: " + SignatureConverter.convertMethodSignature((InvokeInstruction) ins, classContext.getConstantPoolGen())); JavaClassAndMethod proto = Hierarchy.findInvocationLeastUpperBound((InvokeInstruction) ins, classContext.getConstantPoolGen()); if (proto == null) { System.out.println("\tUnknown prototype method"); } else { System.out.println("\tPrototype method: class=" + proto.getJavaClass().getClassName() + ", method=" + proto.getMethod()); } Set<JavaClassAndMethod> calledMethodSet = Hierarchy.resolveMethodCallTargets((InvokeInstruction) ins, classContext.getTypeDataflow(method).getFactAtLocation(location), classContext.getConstantPoolGen()); System.out.println("\tTarget method set: " + calledMethodSet); } } }
upperBound = findInvocationLeastUpperBound(receiverClass, methodName, methodSig, CONCRETE_METHOD, false);
return findInvocationLeastUpperBound(inv, cpg, ANY_METHOD);
public static @CheckForNull JavaClassAndMethod findInvocationLeastUpperBound(JavaClass jClass, String methodName, String methodSig, JavaClassAndMethodChooser methodChooser, boolean invokeInterface) throws ClassNotFoundException { JavaClassAndMethod result = findMethod(jClass, methodName, methodSig, methodChooser); if (result != null) { return result; } if (invokeInterface) { for (JavaClass i : jClass.getInterfaces()) { result = findInvocationLeastUpperBound(i, methodName, methodSig, methodChooser, invokeInterface); if (result != null) { return null; } } } else { JavaClass sClass = jClass.getSuperClass(); if (sClass != null) { return findInvocationLeastUpperBound(sClass, methodName, methodSig, methodChooser, invokeInterface); } } return null; }
return findInvocationLeastUpperBound(jClass, methodName, methodSig, methodChooser, opcode == Constants.INVOKEINTERFACE);
JavaClassAndMethod targetMethod = findInvocationLeastUpperBound(invokeInstruction, cpg, CONCRETE_METHOD); if (targetMethod != null) { result.add(targetMethod);
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, ClassNotFoundException, DataflowAnalysisException { CFG cfg = classContext.getCFG(method); for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Location location = i.next(); Instruction ins = location.getHandle().getInstruction(); if (ins instanceof InvokeInstruction) { if (TARGET_METHOD != null && !((InvokeInstruction) ins).getMethodName(classContext.getConstantPoolGen()).equals(TARGET_METHOD)) { continue; } System.out.println("\n*******************************************************\n"); System.out.println("Method invocation: " + location.getHandle()); System.out.println("\tInvoking: " + SignatureConverter.convertMethodSignature((InvokeInstruction) ins, classContext.getConstantPoolGen())); JavaClassAndMethod proto = Hierarchy.findInvocationLeastUpperBound((InvokeInstruction) ins, classContext.getConstantPoolGen()); if (proto == null) { System.out.println("\tUnknown prototype method"); } else { System.out.println("\tPrototype method: class=" + proto.getJavaClass().getClassName() + ", method=" + proto.getMethod()); } Set<JavaClassAndMethod> calledMethodSet = Hierarchy.resolveMethodCallTargets((InvokeInstruction) ins, classContext.getTypeDataflow(method).getFactAtLocation(location), classContext.getConstantPoolGen()); System.out.println("\tTarget method set: " + calledMethodSet); } } }
upperBound = findInvocationLeastUpperBound(receiverClass, methodName, methodSig, CONCRETE_METHOD, false);