public void analysisSkippedDueToInvokeDynamic(XMethod m) { if (!m.usesInvokeDynamic()) { throw new IllegalArgumentException(); } if (skippedDueToInvokeDynamic.add(m.getMethodDescriptor())) { logAnError(m + " skipped due to invoke_dynamic"); } }
public static boolean assertsFirstParameterIsNonnull(XMethod m) { return (m.getName().equalsIgnoreCase("checkNonNull") || m.getName().equalsIgnoreCase("checkNotNull") // JDK 7 java.util.Objects.requireNonNull(Object) || m.getName().equals("requireNonNull") // org.eclipse.core.runtime.Assert(Object) || m.getName().equalsIgnoreCase("isNotNull") || m.getName().equalsIgnoreCase("assertNotNull")) && m.getSignature().startsWith("(Ljava/lang/Object;"); }
/** * Constructor. * * @param method an XMethod specifying a specific method in a specific class * @throws ClassNotFoundException */ public JavaClassAndMethod(XMethod method) throws ClassNotFoundException { this.javaClass = Repository.lookupClass(method.getClassName()); for (Method m : javaClass.getMethods()) if (m.getName().equals(method.getName()) && m.getSignature().equals(method.getSignature()) && m.isStatic() == method.isStatic()) { this.method = m; return; } throw new IllegalArgumentException("Can't find " + method); }
public boolean parameterMustBeNonNull(XMethod m, int param) { if (param == 0) { if (m.getName().equals("equals") && m.getSignature().equals("(Ljava/lang/Object;)Z") && !m.isStatic()) return false; else if (m.getName().equals("main") && m.getSignature().equals("([Ljava/lang/String;)V") && m.isStatic() && m.isPublic()) return true; else if (assertsFirstParameterIsNonnull(m)) return true; else if (m.getName().equals("compareTo") && m.getSignature().endsWith(";)Z") && !m.isStatic()) return true; } if (!anyAnnotations(NullnessAnnotation.NONNULL)) return false; XMethodParameter xmp = new XMethodParameter(m, param); NullnessAnnotation resolvedAnnotation = getResolvedAnnotation(xmp, true); return resolvedAnnotation == NullnessAnnotation.NONNULL; }
/** * Return whether or not the given method is concrete. * * @param xmethod the method * @return true if the method is concrete, false otherwise */ @Deprecated public static boolean isConcrete(XMethod xmethod) { int accessFlags = xmethod.getAccessFlags(); return (accessFlags & Constants.ACC_ABSTRACT) == 0 && (accessFlags & Constants.ACC_NATIVE) == 0; }
/** * 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; } if (receiverType instanceof NullType) { return Collections.<JavaClassAndMethod>emptySet(); } AnalysisContext analysisContext = AnalysisContext.currentAnalysisContext(); // Get the receiver class. String receiverClassName = ((ObjectType) receiverType).getClassName(); JavaClass receiverClass = analysisContext.lookupClass(receiverClassName); ClassDescriptor receiverDesc = DescriptorFactory.createClassDescriptorFromDottedClassName(receiverClassName); // 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) { upperBound = findInvocationLeastUpperBound( receiverClass, methodName, methodSig, CONCRETE_METHOD, false); } 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.INVOKEVIRTUAL || invokeInstruction.getOpcode() == Constants.INVOKEINTERFACE) && (upperBound == null || !upperBound.getJavaClass().isFinal() && !upperBound.getMethod().isFinal()) && !receiverTypeIsExact; if (virtualCall) { if (!receiverClassName.equals("java.lang.Object")) { // This is a true virtual call: assume that any concrete // subtype method may be called. Set<ClassDescriptor> subTypeSet = analysisContext.getSubtypes2().getSubtypes(receiverDesc); for (ClassDescriptor subtype : subTypeSet) { XMethod concreteSubtypeMethod = findMethod(subtype, methodName, methodSig, false); if (concreteSubtypeMethod != null && (concreteSubtypeMethod.getAccessFlags() & Constants.ACC_ABSTRACT) == 0) { result.add(new JavaClassAndMethod(concreteSubtypeMethod)); } } if (false && subTypeSet.size() > 500) new RuntimeException( receiverClassName + " has " + subTypeSet.size() + " subclasses, " + result.size() + " of which implement " + methodName + methodSig + " " + invokeInstruction) .printStackTrace(System.out); } } return result; }
public boolean choose(XMethod method) { return !method.isStatic(); }
public boolean choose(XMethod method) { return accessFlagsAreConcrete(method.getAccessFlags()); }
@CheckForNull @Override public NullnessAnnotation getResolvedAnnotation(final Object o, boolean getMinimal) { Profiler profiler = Global.getAnalysisCache().getProfiler(); profiler.start(this.getClass()); try { if (o instanceof XMethodParameter) { XMethodParameter mp = (XMethodParameter) o; XMethod m = mp.getMethod(); // TODO: Handle argument to equals specially: generate special // bug code for it int parameterNumber = mp.getParameterNumber(); if (parameterNumber == 0) { if (m.getName().equals("equals") && m.getSignature().equals("(Ljava/lang/Object;)Z") && !m.isStatic()) return NullnessAnnotation.CHECK_FOR_NULL; else if (m.getName().equals("main") && m.getSignature().equals("([Ljava/lang/String;)V") && m.isStatic() && m.isPublic()) return NullnessAnnotation.NONNULL; else if (assertsFirstParameterIsNonnull(m)) return NullnessAnnotation.NONNULL; else if (m.getName().equals("compareTo") && m.getSignature().endsWith(";)Z") && !m.isStatic()) return NullnessAnnotation.NONNULL; } } else if (o instanceof XMethod) { XMethod m = (XMethod) o; String name = m.getName(); String signature = m.getSignature(); if (!m.isStatic() && (name.equals("clone") && signature.equals("()Ljava/lang/Object;") || name.equals("toString") && signature.equals("()Ljava/lang/String;") || m.isPrivate() && name.equals("readResolve") && signature.equals("()Ljava/lang/Object;"))) { NullnessAnnotation result = super.getDirectAnnotation(m); if (result != null) return result; return NullnessAnnotation.NONNULL; } } else if (o instanceof XField) { XField f = (XField) o; if (f.getName().startsWith("this$")) return NullnessAnnotation.NONNULL; } NullnessAnnotation result = super.getResolvedAnnotation(o, getMinimal); return result; } finally { profiler.end(this.getClass()); } }