in src/main/java/org/apache/bcel/verifier/statics/Pass3aVerifier.java [525:575]
public void visitINVOKESPECIAL(final INVOKESPECIAL o) {
try {
// INVOKESPECIAL is a LoadClass; the Class where the referenced method is declared in,
// is therefore resolved/verified.
// INVOKESPECIAL is an InvokeInstruction, the argument and return types are resolved/verified,
// too. So are the allowed method names.
final String className = o.getClassName(constantPoolGen);
final JavaClass jc = Repository.lookupClass(className);
final Method m = getMethodRecursive(jc, o);
if (m == null) {
constraintViolated(o, "Referenced method '" + o.getMethodName(constantPoolGen) + "' with expected signature '"
+ o.getSignature(constantPoolGen) + "' not found in class '" + jc.getClassName() + "'.");
}
JavaClass current = Repository.lookupClass(verifier.getClassName());
if (current.isSuper() && Repository.instanceOf(current, jc) && !current.equals(jc)
&& !o.getMethodName(constantPoolGen).equals(Const.CONSTRUCTOR_NAME)) {
// Special lookup procedure for ACC_SUPER classes.
int supidx = -1;
Method meth = null;
while (supidx != 0) {
supidx = current.getSuperclassNameIndex();
current = Repository.lookupClass(current.getSuperclassName());
final Method[] meths = current.getMethods();
for (final Method meth2 : meths) {
if (meth2.getName().equals(o.getMethodName(constantPoolGen))
&& Type.getReturnType(meth2.getSignature()).equals(o.getReturnType(constantPoolGen))
&& Arrays.equals(Type.getArgumentTypes(meth2.getSignature()), o.getArgumentTypes(constantPoolGen))) {
meth = meth2;
break;
}
}
if (meth != null) {
break;
}
}
if (meth == null) {
constraintViolated(o, "ACC_SUPER special lookup procedure not successful: method '" + o.getMethodName(constantPoolGen)
+ "' with proper signature not declared in superclass hierarchy.");
}
}
} catch (final ClassNotFoundException e) {
// FIXME: maybe not the best way to handle this
throw new AssertionViolatedException("Missing class: " + e, e);
}
}