/** * looks to see if this class (or some class in its hierarchy (besides Object) has implemented the * specified method. * * @param cls the class to look in * @param methodName the method name to look for * @param methodSig the method signature to look for * @return when toString is found * @throws ClassNotFoundException if a super class can't be found */ private static boolean hasMethodInHierarchy(JavaClass cls, String methodName, String methodSig) throws ClassNotFoundException { MethodInfo mi = null; do { String clsName = cls.getClassName(); if (Values.DOTTED_JAVA_LANG_OBJECT.equals(clsName)) { return false; } mi = Statistics.getStatistics() .getMethodStatistics(clsName.replace('.', '/'), methodName, methodSig); cls = cls.getSuperClass(); } while (mi.getNumBytes() == 0); return true; }
/** * overrides the visitor to look for calls to static methods that are known to return immutable * collections It records those variables, and documents if what the method returns is one of * those objects. */ @Override public void sawOpcode(int seen) { ImmutabilityType seenImmutable = null; try { stack.precomputation(this); switch (seen) { case INVOKESTATIC: { String className = getClassConstantOperand(); String methodName = getNameConstantOperand(); if (IMMUTABLE_PRODUCING_METHODS.contains(className + '.' + methodName)) { seenImmutable = ImmutabilityType.IMMUTABLE; break; } } // $FALL-THROUGH$ case INVOKEINTERFACE: case INVOKESPECIAL: case INVOKEVIRTUAL: { String className = getClassConstantOperand(); String methodName = getNameConstantOperand(); String signature = getSigConstantOperand(); MethodInfo mi = Statistics.getStatistics().getMethodStatistics(className, methodName, signature); seenImmutable = mi.getImmutabilityType(); if (seenImmutable == ImmutabilityType.UNKNOWN) seenImmutable = null; } break; case ARETURN: { if (stack.getStackDepth() > 0) { OpcodeStack.Item item = stack.getStackItem(0); ImmutabilityType type = (ImmutabilityType) item.getUserValue(); if (type == null) type = ImmutabilityType.UNKNOWN; switch (imType) { case UNKNOWN: switch (type) { case IMMUTABLE: imType = ImmutabilityType.IMMUTABLE; break; case POSSIBLY_IMMUTABLE: imType = ImmutabilityType.POSSIBLY_IMMUTABLE; break; default: imType = ImmutabilityType.MUTABLE; break; } break; case IMMUTABLE: if (type != ImmutabilityType.IMMUTABLE) { imType = ImmutabilityType.POSSIBLY_IMMUTABLE; } break; case POSSIBLY_IMMUTABLE: break; case MUTABLE: if (type == ImmutabilityType.IMMUTABLE) { imType = ImmutabilityType.POSSIBLY_IMMUTABLE; } break; } } break; } default: break; } } finally { stack.sawOpcode(this, seen); if (seenImmutable != null) { if (stack.getStackDepth() > 0) { OpcodeStack.Item item = stack.getStackItem(0); item.setUserValue(seenImmutable); } } } }