in src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java [1678:1728]
public void visitINVOKESPECIAL(final INVOKESPECIAL o) {
try {
// Don't init an object twice.
if (o.getMethodName(cpg).equals(Const.CONSTRUCTOR_NAME) && !(stack().peek(o.getArgumentTypes(cpg).length) instanceof UninitializedObjectType)) {
constraintViolated(o,
"Possibly initializing object twice."
+ " A valid instruction sequence must not have an uninitialized object on the operand stack or in a local variable"
+ " during a backwards branch, or in a local variable in code protected by an exception handler."
+ " Please see The Java Virtual Machine Specification, Second Edition, 4.9.4 (pages 147 and 148) for details.");
}
// the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o).
final int nargs = visitInvokeInternals(o);
Type objref = stack().peek(nargs);
if (objref == Type.NULL) {
return;
}
if (!(objref instanceof ReferenceType)) {
constraintViolated(o, "Expecting a reference type as 'objectref' on the stack, not a '" + objref + "'.");
}
String objRefClassName = null;
if (!o.getMethodName(cpg).equals(Const.CONSTRUCTOR_NAME)) {
referenceTypeIsInitialized(o, (ReferenceType) objref);
if (!(objref instanceof ObjectType)) {
if (!(objref instanceof ArrayType)) { // could be a ReturnaddressType
constraintViolated(o, "Expecting an ObjectType as 'objectref' on the stack, not a '" + objref + "'.");
} else {
objref = GENERIC_ARRAY;
}
}
objRefClassName = ((ObjectType) objref).getClassName();
} else {
if (!(objref instanceof UninitializedObjectType)) {
constraintViolated(o, "Expecting an UninitializedObjectType as 'objectref' on the stack, not a '" + objref
+ "'. Otherwise, you couldn't invoke a method since an array has no methods (not to speak of a return address).");
}
objRefClassName = ((UninitializedObjectType) objref).getInitialized().getClassName();
}
final String theClass = o.getClassName(cpg);
if (!Repository.instanceOf(objRefClassName, theClass)) {
constraintViolated(o, "The 'objref' item '" + objref + "' does not implement '" + theClass + "' as expected.");
}
} catch (final ClassNotFoundException e) {
// FIXME: maybe not the best way to handle this
throw new AssertionViolatedException("Missing class: " + e, e);
}
}